mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 16:20:08 +00:00
Merge pull request #11098 from opensourcerouting/zapi-mrib-v6
zebra, pimd: add IPv6 support to NEXTHOP_LOOKUP_MRIB
This commit is contained in:
commit
b6f754f89d
@ -250,7 +250,7 @@ Zebra Protocol Commands
|
||||
+------------------------------------+-------+
|
||||
| ZEBRA_INTERFACE_DISABLE_RADV | 43 |
|
||||
+------------------------------------+-------+
|
||||
| ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB | 44 |
|
||||
| ZEBRA_NEXTHOP_LOOKUP_MRIB | 44 |
|
||||
+------------------------------------+-------+
|
||||
| ZEBRA_INTERFACE_LINK_PARAMS | 45 |
|
||||
+------------------------------------+-------+
|
||||
|
@ -370,7 +370,7 @@ static const struct zebra_desc_table command_types[] = {
|
||||
DESC_ENTRY(ZEBRA_BFD_CLIENT_DEREGISTER),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_DISABLE_RADV),
|
||||
DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB),
|
||||
DESC_ENTRY(ZEBRA_NEXTHOP_LOOKUP_MRIB),
|
||||
DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS),
|
||||
DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD),
|
||||
DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE),
|
||||
|
@ -143,7 +143,7 @@ typedef enum {
|
||||
ZEBRA_BFD_CLIENT_DEREGISTER,
|
||||
ZEBRA_INTERFACE_ENABLE_RADV,
|
||||
ZEBRA_INTERFACE_DISABLE_RADV,
|
||||
ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB,
|
||||
ZEBRA_NEXTHOP_LOOKUP_MRIB,
|
||||
ZEBRA_INTERFACE_LINK_PARAMS,
|
||||
ZEBRA_MPLS_LABELS_ADD,
|
||||
ZEBRA_MPLS_LABELS_DELETE,
|
||||
|
@ -37,22 +37,6 @@ void pim_nht_bsr_del(struct pim_instance *pim, struct in_addr addr)
|
||||
{
|
||||
}
|
||||
|
||||
int zclient_lookup_nexthop(struct pim_instance *pim,
|
||||
struct pim_zlookup_nexthop nexthop_tab[],
|
||||
const int tab_size, pim_addr addr,
|
||||
int max_lookup)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void zclient_lookup_new(void)
|
||||
{
|
||||
}
|
||||
|
||||
void zclient_lookup_free(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* PIM register
|
||||
*/
|
||||
|
@ -31,6 +31,8 @@ typedef struct in_addr pim_addr;
|
||||
#define PIM_ADDRSTRLEN INET_ADDRSTRLEN
|
||||
#define PIM_AF AF_INET
|
||||
#define PIM_AFI AFI_IP
|
||||
#define PIM_IPADDR IPADDR_V4
|
||||
#define ipaddr_pim ipaddr_v4
|
||||
#define PIM_MAX_BITLEN IPV4_MAX_BITLEN
|
||||
#define PIM_AF_NAME "ip"
|
||||
|
||||
@ -52,6 +54,8 @@ typedef struct in6_addr pim_addr;
|
||||
#define PIM_ADDRSTRLEN INET6_ADDRSTRLEN
|
||||
#define PIM_AF AF_INET6
|
||||
#define PIM_AFI AFI_IP6
|
||||
#define PIM_IPADDR IPADDR_V6
|
||||
#define ipaddr_pim ipaddr_v6
|
||||
#define PIM_MAX_BITLEN IPV6_MAX_BITLEN
|
||||
#define PIM_AF_NAME "ipv6"
|
||||
|
||||
|
@ -165,7 +165,7 @@ static int zclient_read_nexthop(struct pim_instance *pim,
|
||||
uint8_t version;
|
||||
vrf_id_t vrf_id;
|
||||
uint16_t command = 0;
|
||||
pim_addr raddr;
|
||||
struct ipaddr raddr;
|
||||
uint8_t distance;
|
||||
uint32_t metric;
|
||||
int nexthop_num;
|
||||
@ -177,7 +177,7 @@ static int zclient_read_nexthop(struct pim_instance *pim,
|
||||
|
||||
s = zlookup->ibuf;
|
||||
|
||||
while (command != ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB) {
|
||||
while (command != ZEBRA_NEXTHOP_LOOKUP_MRIB) {
|
||||
stream_reset(s);
|
||||
err = zclient_read_header(s, zlookup->sock, &length, &marker,
|
||||
&version, &vrf_id, &command);
|
||||
@ -197,15 +197,14 @@ static int zclient_read_nexthop(struct pim_instance *pim,
|
||||
}
|
||||
}
|
||||
|
||||
#if PIM_IPV == 4
|
||||
raddr.s_addr = stream_get_ipv4(s);
|
||||
#else
|
||||
stream_get(&raddr, s, sizeof(struct in6_addr));
|
||||
#endif
|
||||
if (pim_addr_cmp(raddr, addr))
|
||||
zlog_warn("%s: address mismatch: addr=%pPAs(%s) raddr=%pPAs",
|
||||
stream_get_ipaddr(s, &raddr);
|
||||
|
||||
if (raddr.ipa_type != PIM_IPADDR ||
|
||||
pim_addr_cmp(raddr.ipaddr_pim, addr)) {
|
||||
zlog_warn("%s: address mismatch: addr=%pPA(%s) raddr=%pIA",
|
||||
__func__, &addr, pim->vrf->name, &raddr);
|
||||
/* warning only */
|
||||
/* warning only */
|
||||
}
|
||||
|
||||
distance = stream_getc(s);
|
||||
metric = stream_getl(s);
|
||||
@ -221,8 +220,9 @@ static int zclient_read_nexthop(struct pim_instance *pim,
|
||||
for (i = 0; i < nexthop_num; ++i) {
|
||||
vrf_id_t nexthop_vrf_id;
|
||||
enum nexthop_types_t nexthop_type;
|
||||
struct pim_neighbor *nbr;
|
||||
struct prefix p;
|
||||
struct in_addr nh_ip4;
|
||||
struct in6_addr nh_ip6;
|
||||
ifindex_t nh_ifi;
|
||||
|
||||
nexthop_vrf_id = stream_getl(s);
|
||||
nexthop_type = stream_getc(s);
|
||||
@ -250,21 +250,27 @@ static int zclient_read_nexthop(struct pim_instance *pim,
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV4_IFINDEX:
|
||||
case NEXTHOP_TYPE_IPV4:
|
||||
nexthop_tab[num_ifindex].nexthop_addr.s_addr =
|
||||
stream_get_ipv4(s);
|
||||
nexthop_tab[num_ifindex].ifindex = stream_getl(s);
|
||||
nh_ip4.s_addr = stream_get_ipv4(s);
|
||||
nh_ifi = stream_getl(s);
|
||||
#if PIM_IPV == 4
|
||||
nexthop_tab[num_ifindex].nexthop_addr = nh_ip4;
|
||||
nexthop_tab[num_ifindex].ifindex = nh_ifi;
|
||||
++num_ifindex;
|
||||
#else
|
||||
zlog_warn("cannot use IPv4 nexthop %pI4 for IPv6 %pPA",
|
||||
&nh_ip4, &addr);
|
||||
#endif
|
||||
break;
|
||||
case NEXTHOP_TYPE_IPV6_IFINDEX:
|
||||
stream_get(&nexthop_tab[num_ifindex].nexthop_addr, s,
|
||||
sizeof(struct in6_addr));
|
||||
nexthop_tab[num_ifindex].ifindex = stream_getl(s);
|
||||
stream_get(&nh_ip6, s, sizeof(nh_ip6));
|
||||
nh_ifi = stream_getl(s);
|
||||
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = IPV6_MAX_BITLEN;
|
||||
memcpy(&p.u.prefix6,
|
||||
&nexthop_tab[num_ifindex].nexthop_addr,
|
||||
sizeof(struct in6_addr));
|
||||
#if PIM_IPV == 6
|
||||
nexthop_tab[num_ifindex].nexthop_addr = nh_ip6;
|
||||
nexthop_tab[num_ifindex].ifindex = nh_ifi;
|
||||
++num_ifindex;
|
||||
#else
|
||||
/* RFC 5549 v4-over-v6 nexthop handling */
|
||||
|
||||
/*
|
||||
* If we are sending v6 secondary assume we receive v6
|
||||
@ -275,26 +281,35 @@ static int zclient_read_nexthop(struct pim_instance *pim,
|
||||
nexthop_vrf_id);
|
||||
|
||||
if (!ifp)
|
||||
nbr = NULL;
|
||||
else if (pim->send_v6_secondary)
|
||||
break;
|
||||
|
||||
struct pim_neighbor *nbr;
|
||||
|
||||
if (pim->send_v6_secondary) {
|
||||
struct prefix p;
|
||||
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = IPV6_MAX_BITLEN;
|
||||
p.u.prefix6 = nh_ip6;
|
||||
|
||||
nbr = pim_neighbor_find_by_secondary(ifp, &p);
|
||||
else
|
||||
} else
|
||||
nbr = pim_neighbor_find_if(ifp);
|
||||
|
||||
if (nbr) {
|
||||
nexthop_tab[num_ifindex].nexthop_addr =
|
||||
nbr->source_addr;
|
||||
}
|
||||
if (!nbr)
|
||||
break;
|
||||
|
||||
nexthop_tab[num_ifindex].nexthop_addr =
|
||||
nbr->source_addr;
|
||||
nexthop_tab[num_ifindex].ifindex = nh_ifi;
|
||||
++num_ifindex;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
{
|
||||
zlog_warn(
|
||||
"%s: found non-ifindex nexthop type=%d for address %pPAs(%s)",
|
||||
__func__, nexthop_type, &addr,
|
||||
pim->vrf->name);
|
||||
}
|
||||
zlog_warn(
|
||||
"%s: found non-ifindex nexthop type=%d for address %pPAs(%s)",
|
||||
__func__, nexthop_type, &addr, pim->vrf->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -308,6 +323,7 @@ static int zclient_lookup_nexthop_once(struct pim_instance *pim,
|
||||
{
|
||||
struct stream *s;
|
||||
int ret;
|
||||
struct ipaddr ipaddr;
|
||||
|
||||
if (PIM_DEBUG_PIM_NHT_DETAIL)
|
||||
zlog_debug("%s: addr=%pPAs(%s)", __func__, &addr,
|
||||
@ -329,15 +345,13 @@ static int zclient_lookup_nexthop_once(struct pim_instance *pim,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipaddr.ipa_type = PIM_IPADDR;
|
||||
ipaddr.ipaddr_pim = addr;
|
||||
|
||||
s = zlookup->obuf;
|
||||
stream_reset(s);
|
||||
zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB,
|
||||
pim->vrf->vrf_id);
|
||||
#if PIM_IPV == 4
|
||||
stream_put_in_addr(s, &addr);
|
||||
#else
|
||||
stream_write(s, (uint8_t *)&addr, 16);
|
||||
#endif
|
||||
zclient_create_header(s, ZEBRA_NEXTHOP_LOOKUP_MRIB, pim->vrf->vrf_id);
|
||||
stream_put_ipaddr(s, &ipaddr);
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
|
||||
ret = writen(zlookup->sock, s->data, stream_get_endp(s));
|
||||
@ -483,6 +497,7 @@ void pim_zlookup_show_ip_multicast(struct vty *vty)
|
||||
}
|
||||
}
|
||||
|
||||
#if PIM_IPV == 4
|
||||
int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
|
||||
{
|
||||
struct stream *s = zlookup->obuf;
|
||||
@ -571,3 +586,4 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -55,6 +55,7 @@ pim_common = \
|
||||
pimd/pim_util.c \
|
||||
pimd/pim_vty.c \
|
||||
pimd/pim_zebra.c \
|
||||
pimd/pim_zlookup.c \
|
||||
pimd/pim_vxlan.c \
|
||||
pimd/pimd.c \
|
||||
# end
|
||||
@ -75,7 +76,6 @@ pimd_pimd_SOURCES = \
|
||||
pimd/pim_msdp_socket.c \
|
||||
pimd/pim_register.c \
|
||||
pimd/pim_signals.c \
|
||||
pimd/pim_zlookup.c \
|
||||
pimd/pim_zpthread.c \
|
||||
pimd/pim_mroute_msg.c \
|
||||
# end
|
||||
|
@ -424,6 +424,9 @@ extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
|
||||
extern struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id,
|
||||
struct in_addr addr,
|
||||
struct route_node **rn_out);
|
||||
extern struct route_entry *rib_match_ipv6_multicast(vrf_id_t vrf_id,
|
||||
struct in6_addr addr,
|
||||
struct route_node **rn_out);
|
||||
|
||||
extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
|
||||
vrf_id_t vrf_id);
|
||||
|
@ -659,11 +659,18 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
|
||||
* Modified version of zsend_ipv4_nexthop_lookup(): Query unicast rib if
|
||||
* nexthop is not found on mrib. Returns both route metric and protocol
|
||||
* distance.
|
||||
*
|
||||
* *XXX* this ZAPI call is slated to be removed at some point in the future
|
||||
* since MRIB support in PIM is hopelessly broken in its interactions with NHT.
|
||||
* The plan is to make pimd use NHT to receive URIB and MRIB in parallel and
|
||||
* make the decision there, which will obsolete this ZAPI op.
|
||||
* (Otherwise we would need to implement sending NHT updates for the result of
|
||||
* this "URIB-MRIB-combined" table, but we only decide that here on the fly,
|
||||
* so it'd be rather complex to do NHT for.)
|
||||
*/
|
||||
static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
|
||||
struct in_addr addr,
|
||||
struct route_entry *re,
|
||||
struct zebra_vrf *zvrf)
|
||||
static int zsend_nexthop_lookup_mrib(struct zserv *client, struct ipaddr *addr,
|
||||
struct route_entry *re,
|
||||
struct zebra_vrf *zvrf)
|
||||
{
|
||||
struct stream *s;
|
||||
unsigned long nump;
|
||||
@ -675,8 +682,8 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
|
||||
stream_reset(s);
|
||||
|
||||
/* Fill in result. */
|
||||
zclient_create_header(s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
|
||||
stream_put_in_addr(s, &addr);
|
||||
zclient_create_header(s, ZEBRA_NEXTHOP_LOOKUP_MRIB, zvrf_id(zvrf));
|
||||
stream_put_ipaddr(s, addr);
|
||||
|
||||
if (re) {
|
||||
struct nexthop_group *nhg;
|
||||
@ -2229,14 +2236,28 @@ static void zread_route_del(ZAPI_HANDLER_ARGS)
|
||||
}
|
||||
|
||||
/* MRIB Nexthop lookup for IPv4. */
|
||||
static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
|
||||
static void zread_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct in_addr addr;
|
||||
struct route_entry *re;
|
||||
struct ipaddr addr;
|
||||
struct route_entry *re = NULL;
|
||||
|
||||
STREAM_GET(&addr.s_addr, msg, IPV4_MAX_BYTELEN);
|
||||
re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr, NULL);
|
||||
zsend_ipv4_nexthop_lookup_mrib(client, addr, re, zvrf);
|
||||
STREAM_GET_IPADDR(msg, &addr);
|
||||
|
||||
switch (addr.ipa_type) {
|
||||
case IPADDR_V4:
|
||||
re = rib_match_ipv4_multicast(zvrf_id(zvrf), addr.ipaddr_v4,
|
||||
NULL);
|
||||
break;
|
||||
case IPADDR_V6:
|
||||
re = rib_match_ipv6_multicast(zvrf_id(zvrf), addr.ipaddr_v6,
|
||||
NULL);
|
||||
break;
|
||||
case IPADDR_NONE:
|
||||
/* ??? */
|
||||
goto stream_failure;
|
||||
}
|
||||
|
||||
zsend_nexthop_lookup_mrib(client, &addr, re, zvrf);
|
||||
|
||||
stream_failure:
|
||||
return;
|
||||
@ -3685,7 +3706,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
||||
[ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete,
|
||||
[ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add,
|
||||
[ZEBRA_REDISTRIBUTE_DEFAULT_DELETE] = zebra_redistribute_default_delete,
|
||||
[ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB] = zread_ipv4_nexthop_lookup_mrib,
|
||||
[ZEBRA_NEXTHOP_LOOKUP_MRIB] = zread_nexthop_lookup_mrib,
|
||||
[ZEBRA_HELLO] = zread_hello,
|
||||
[ZEBRA_NEXTHOP_REGISTER] = zread_rnh_register,
|
||||
[ZEBRA_NEXTHOP_UNREGISTER] = zread_rnh_unregister,
|
||||
|
@ -487,6 +487,62 @@ struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id,
|
||||
return re;
|
||||
}
|
||||
|
||||
struct route_entry *rib_match_ipv6_multicast(vrf_id_t vrf_id,
|
||||
struct in6_addr addr,
|
||||
struct route_node **rn_out)
|
||||
{
|
||||
struct route_entry *re = NULL, *mre = NULL, *ure = NULL;
|
||||
struct route_node *m_rn = NULL, *u_rn = NULL;
|
||||
union g_addr gaddr = {.ipv6 = addr};
|
||||
|
||||
switch (zrouter.ipv4_multicast_mode) {
|
||||
case MCAST_MRIB_ONLY:
|
||||
return rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr,
|
||||
rn_out);
|
||||
case MCAST_URIB_ONLY:
|
||||
return rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, rn_out);
|
||||
case MCAST_NO_CONFIG:
|
||||
case MCAST_MIX_MRIB_FIRST:
|
||||
re = mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr,
|
||||
&m_rn);
|
||||
if (!mre)
|
||||
re = ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id,
|
||||
&gaddr, &u_rn);
|
||||
break;
|
||||
case MCAST_MIX_DISTANCE:
|
||||
mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
|
||||
ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
|
||||
if (mre && ure)
|
||||
re = ure->distance < mre->distance ? ure : mre;
|
||||
else if (mre)
|
||||
re = mre;
|
||||
else if (ure)
|
||||
re = ure;
|
||||
break;
|
||||
case MCAST_MIX_PFXLEN:
|
||||
mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
|
||||
ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
|
||||
if (mre && ure)
|
||||
re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre;
|
||||
else if (mre)
|
||||
re = mre;
|
||||
else if (ure)
|
||||
re = ure;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rn_out)
|
||||
*rn_out = (re == mre) ? m_rn : u_rn;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_RIB)
|
||||
zlog_debug("%s: %pI6: vrf: %s(%u) found %s, using %s", __func__,
|
||||
&addr, vrf_id_to_name(vrf_id), vrf_id,
|
||||
mre ? (ure ? "MRIB+URIB" : "MRIB")
|
||||
: ure ? "URIB" : "nothing",
|
||||
re == ure ? "URIB" : re == mre ? "MRIB" : "none");
|
||||
return re;
|
||||
}
|
||||
|
||||
struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
|
||||
{
|
||||
struct route_table *table;
|
||||
|
Loading…
Reference in New Issue
Block a user