diff --git a/lib/zclient.h b/lib/zclient.h index ccb7b0509d..7808fd804f 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -114,6 +114,7 @@ struct zclient #define ZAPI_MESSAGE_METRIC 0x08 #define ZAPI_MESSAGE_TAG 0x10 #define ZAPI_MESSAGE_MTU 0x20 +#define ZAPI_MESSAGE_SRCPFX 0x40 /* Zserv protocol message header */ struct zserv_header diff --git a/zebra/connected.c b/zebra/connected.c index ebd948252e..0ceaddc8e3 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -201,11 +201,11 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc) return; rib_add (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, + 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, 0); rib_add (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, + 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) @@ -331,10 +331,10 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc) /* Same logic as for connected_up_ipv4(): push the changes into the head. */ rib_delete (AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, ifp->ifindex, 0); + 0, 0, &p, NULL, NULL, ifp->ifindex, 0); rib_delete (AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, ifp->ifindex, 0); + 0, 0, &p, NULL, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing", @@ -407,7 +407,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) #endif rib_add (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, NULL, ifp->ifindex, + 0, 0, &p, NULL, NULL, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) @@ -507,7 +507,7 @@ connected_down_ipv6 (struct interface *ifp, struct connected *ifc) return; rib_delete (AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, ifp->ifindex, 0); + 0, 0, &p, NULL, NULL, ifp->ifindex, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing", diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index fd059dfee7..20a0472195 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -992,17 +992,17 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, 0, 0); + 0, zebra_flags, &p, NULL, NULL, 0, 0); union g_addr ggate = { .ipv4 = gate.sin.sin_addr }; if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, &ggate, NULL, 0, 0, 0, 0, 0); + &p, NULL, &ggate, NULL, 0, 0, 0, 0, 0); else rib_delete (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, &ggate, 0, 0); + 0, zebra_flags, &p, NULL, &ggate, 0, 0); } if (dest.sa.sa_family == AF_INET6) { @@ -1034,18 +1034,18 @@ rtm_read (struct rt_msghdr *rtm) */ if (rtm->rtm_type == RTM_CHANGE) rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, NULL, 0, 0); + 0, zebra_flags, &p, NULL, NULL, 0, 0); union g_addr ggate = { .ipv6 = gate.sin6.sin6_addr }; if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) rib_add (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, &ggate, NULL, ifindex, + 0, zebra_flags, &p, NULL, &ggate, NULL, ifindex, 0, 0, 0, 0); else rib_delete (AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, &ggate, ifindex, 0); + 0, zebra_flags, &p, NULL, &ggate, ifindex, 0); } } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 4b2aabd186..435122cfe7 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -519,7 +519,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char gate = (union g_addr *)&nhop->gate.ipv4; rib_add (AFI_IP, SAFI_UNICAST, rib->vrf_id, ZEBRA_ROUTE_TABLE, - rib->table, 0, &p, gate, (union g_addr *)&nhop->src.ipv4, + rib->table, 0, &p, NULL, gate, (union g_addr *)&nhop->src.ipv4, nhop->ifindex, zebrad.rtm_table_default, rib->metric, rib->mtu, zebra_import_table_distance[AFI_IP][rib->table]); @@ -541,7 +541,7 @@ zebra_add_import_table_entry (struct route_node *rn, struct rib *rib, const char for (nhop = rib->nexthop; nhop; nhop = nhop->next) rib_copy_nexthops(newrib, nhop); - rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, newrib); + rib_add_multipath(AFI_IP, SAFI_UNICAST, &p, NULL, newrib); } } } @@ -565,7 +565,7 @@ zebra_del_import_table_entry (struct route_node *rn, struct rib *rib) p.u.prefix4 = rn->p.u.prefix4; rib_delete (AFI_IP, SAFI_UNICAST, rib->vrf_id, ZEBRA_ROUTE_TABLE, - rib->table, rib->flags, &p, NULL, + rib->table, rib->flags, &p, NULL, NULL, 0, zebrad.rtm_table_default); } /* DD: Add IPv6 code */ diff --git a/zebra/rib.h b/zebra/rib.h index d80ea6cbd8..fceab93d1a 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -342,17 +342,17 @@ extern int rib_uninstall_kernel (struct route_node *rn, struct rib *rib); * also implicitly withdraw equal prefix of same type. */ extern int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, - union g_addr *gate, union g_addr *src, + struct prefix_ipv6 *src_p, union g_addr *gate, union g_addr *src, ifindex_t ifindex, u_int32_t table_id, u_int32_t, u_int32_t, u_char); extern int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *, - struct rib *); + struct prefix_ipv6 *src_p, struct rib *); extern int rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, - union g_addr *gate, ifindex_t ifindex, - u_int32_t table_id); + struct prefix_ipv6 *src_p, union g_addr *gate, + ifindex_t ifindex, u_int32_t table_id); extern struct rib *rib_match (afi_t afi, safi_t safi, vrf_id_t, union g_addr *, struct route_node **rn_out); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index d2781f4c4e..585b80f979 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -238,7 +238,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (!tb[RTA_MULTIPATH]) rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, gate, src, index, + 0, flags, &p, NULL, gate, src, index, table, metric, mtu, 0); else { @@ -296,7 +296,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib); } } if (rtm->rtm_family == AF_INET6) @@ -306,7 +306,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h, p.prefixlen = rtm->rtm_dst_len; rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, flags, &p, gate, src, index, + 0, flags, &p, NULL, gate, src, index, table, metric, mtu, 0); } @@ -431,7 +431,7 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, { if (!tb[RTA_MULTIPATH]) rib_add (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, 0, &p, gate, src, index, + 0, 0, &p, NULL, gate, src, index, table, metric, mtu, 0); else { @@ -490,12 +490,12 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, if (rib->nexthop_num == 0) XFREE (MTYPE_RIB, rib); else - rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, rib); + rib_add_multipath (AFI_IP, SAFI_UNICAST, &p, NULL, rib); } } else rib_delete (AFI_IP, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, 0, zebra_flags, - &p, gate, index, table); + &p, NULL, gate, index, table); } if (rtm->rtm_family == AF_INET6) @@ -516,11 +516,11 @@ netlink_route_change_read_unicast (struct sockaddr_nl *snl, struct nlmsghdr *h, if (h->nlmsg_type == RTM_NEWROUTE) rib_add (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, 0, &p, gate, src, index, + 0, 0, &p, NULL, gate, src, index, table, metric, mtu, 0); else rib_delete (AFI_IP6, SAFI_UNICAST, vrf_id, ZEBRA_ROUTE_KERNEL, - 0, zebra_flags, &p, gate, index, table); + 0, zebra_flags, &p, NULL, gate, index, table); } return 0; diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index c6eee75174..1007d0ac18 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -94,7 +94,7 @@ handle_route_entry (mib2_ipRouteEntry_t *routeEntry) ggateway = (union g_addr *)&gateway; rib_add (AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0, - zebra_flags, &prefix, ggateway, NULL, 0, 0, 0, 0, 0); + zebra_flags, &prefix, NULL, ggateway, NULL, 0, 0, 0, 0, 0); } void diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 59893b1a0f..d638ceab7f 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2585,7 +2585,7 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p, vrf_id_t vrf_id) int rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, - struct rib *rib) + struct prefix_ipv6 *src_p, struct rib *rib) { struct route_table *table; struct route_node *rn; @@ -2674,8 +2674,8 @@ rib_add_multipath (afi_t afi, safi_t safi, struct prefix *p, int rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, - int flags, struct prefix *p, union g_addr *gate, ifindex_t ifindex, - u_int32_t table_id) + int flags, struct prefix *p, struct prefix_ipv6 *src_p, + union g_addr *gate, ifindex_t ifindex, u_int32_t table_id) { struct route_table *table; struct route_node *rn; @@ -2815,7 +2815,8 @@ rib_delete (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int rib_add (afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance, int flags, struct prefix *p, - union g_addr *gate, union g_addr *src, ifindex_t ifindex, + struct prefix_ipv6 *src_p, union g_addr *gate, + union g_addr *src, ifindex_t ifindex, u_int32_t table_id, u_int32_t metric, u_int32_t mtu, u_char distance) { diff --git a/zebra/zserv.c b/zebra/zserv.c index 6f72ad1758..fd40ed123b 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -1149,7 +1149,7 @@ zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) /* Table */ rib->table = zvrf->table_id; - ret = rib_add_multipath (AFI_IP, safi, &p, rib); + ret = rib_add_multipath (AFI_IP, safi, &p, NULL, rib); /* Stats */ if (ret > 0) @@ -1243,7 +1243,7 @@ zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) table_id = zvrf->table_id; rib_delete (AFI_IP, api.safi, zvrf_id (zvrf), api.type, api.instance, - api.flags, &p, nexthop_p, ifindex, table_id); + api.flags, &p, NULL, nexthop_p, ifindex, table_id); client->v4_route_del_cnt++; return 0; } @@ -1378,7 +1378,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct /* Table */ rib->table = zvrf->table_id; - ret = rib_add_multipath (AFI_IP6, safi, &p, rib); + ret = rib_add_multipath (AFI_IP6, safi, &p, NULL, rib); /* Stats */ if (ret > 0) client->v4_route_add_cnt++; @@ -1399,6 +1399,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) u_char nexthop_num; u_char nexthop_type; struct prefix p; + struct prefix_ipv6 src_p, *src_pp; safi_t safi; static struct in6_addr nexthops[MULTIPATH_NUM]; static unsigned int ifindices[MULTIPATH_NUM]; @@ -1426,6 +1427,17 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) p.prefixlen = stream_getc (s); stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); + if (CHECK_FLAG (message, ZAPI_MESSAGE_SRCPFX)) + { + memset (&src_p, 0, sizeof (struct prefix_ipv6)); + src_p.family = AF_INET6; + src_p.prefixlen = stream_getc (s); + stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); + src_pp = &src_p; + } + else + src_pp = NULL; + /* We need to give nh-addr, nh-ifindex with the same next-hop object * to the rib to ensure that IPv6 multipathing works; need to coalesce * these. Clients should send the same number of paired set of @@ -1500,7 +1512,7 @@ zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf) rib->vrf_id = zvrf_id (zvrf); rib->table = zvrf->table_id; - ret = rib_add_multipath (AFI_IP6, safi, &p, rib); + ret = rib_add_multipath (AFI_IP6, safi, &p, src_pp, rib); /* Stats */ if (ret > 0) client->v6_route_add_cnt++; @@ -1521,6 +1533,7 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) union g_addr *pnexthop = NULL; unsigned long ifindex; struct prefix p; + struct prefix_ipv6 src_p, *src_pp; s = client->ibuf; ifindex = 0; @@ -1539,6 +1552,17 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) p.prefixlen = stream_getc (s); stream_get (&p.u.prefix6, s, PSIZE (p.prefixlen)); + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_SRCPFX)) + { + memset (&src_p, 0, sizeof (struct prefix_ipv6)); + src_p.family = AF_INET6; + src_p.prefixlen = stream_getc (s); + stream_get (&src_p.prefix, s, PSIZE (src_p.prefixlen)); + src_pp = &src_p; + } + else + src_pp = NULL; + /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { @@ -1582,10 +1606,10 @@ zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf) if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, - api.flags, &p, NULL, ifindex, client->rtm_table); + api.flags, &p, src_pp, NULL, ifindex, client->rtm_table); else rib_delete (AFI_IP6, api.safi, zvrf_id (zvrf), api.type, api.instance, - api.flags, &p, pnexthop, ifindex, client->rtm_table); + api.flags, &p, src_pp, pnexthop, ifindex, client->rtm_table); client->v6_route_del_cnt++; return 0;