Merge pull request #1618 from donaldsharp/zebra_startup_ordering

zebra route-leaking for static routes
This commit is contained in:
Philippe Guibert 2018-01-23 08:25:01 +01:00 committed by GitHub
commit d6fed38109
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 657 additions and 173 deletions

View File

@ -166,6 +166,7 @@ zebra_route(int add, int family, const unsigned char *pref, unsigned short plen,
api.type = ZEBRA_ROUTE_BABEL;
api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.prefix = quagga_prefix;
if(metric >= KERNEL_INFINITY) {

View File

@ -1001,6 +1001,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id;
api.nh_vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;
@ -1253,6 +1254,7 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = peer->bgp->vrf_id;
api.nh_vrf_id = peer->bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
api.prefix = *p;

View File

@ -396,6 +396,7 @@ static void vnc_zebra_route_msg(struct prefix *p, unsigned int nhp_count,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_VNC;
api.safi = SAFI_UNICAST;
api.prefix = *p;

View File

@ -366,6 +366,7 @@ void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
@ -407,6 +408,7 @@ void eigrp_zebra_route_delete(struct prefix *p)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_EIGRP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));

View File

@ -261,6 +261,7 @@ static void isis_zebra_route_add_route(struct prefix *prefix,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;
@ -329,6 +330,7 @@ static void isis_zebra_route_del_route(struct prefix *prefix,
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_ISIS;
api.safi = SAFI_UNICAST;
api.prefix = *prefix;

View File

@ -219,6 +219,18 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
struct vrf *vrf;
struct interface if_tmp;
if (vrf_id == VRF_UNKNOWN) {
struct interface *ifp;
RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) {
ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
if (ifp)
return ifp;
}
return NULL;
}
vrf = vrf_lookup_by_id(vrf_id);
if (!vrf)
return NULL;

View File

@ -452,6 +452,13 @@ struct nbr_connected {
/* Prototypes. */
extern int if_cmp_name_func(char *, char *);
/*
* Passing in VRF_UNKNOWN is a valid thing to do, unless we
* are creating a new interface.
*
* This is useful for vrf route-leaking. So more than anything
* else think before you use VRF_UNKNOWN
*/
extern void if_update_to_new_vrf(struct interface *, vrf_id_t vrf_id);
extern struct interface *if_create(const char *name, vrf_id_t vrf_id);
extern struct interface *if_lookup_by_index(ifindex_t, vrf_id_t vrf_id);

View File

@ -942,6 +942,8 @@ int zapi_route_encode(u_char cmd, struct stream *s, struct zapi_route *api)
}
stream_putw(s, api->nexthop_num);
if (api->nexthop_num)
stream_putw(s, api->nh_vrf_id);
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];
@ -1091,6 +1093,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
return -1;
}
if (api->nexthop_num)
STREAM_GETW(s, api->nh_vrf_id);
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];

View File

@ -281,6 +281,7 @@ struct zapi_route {
u_int32_t mtu;
vrf_id_t vrf_id;
vrf_id_t nh_vrf_id;
struct ethaddr rmac;
};
@ -420,6 +421,11 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
vrf_id_t *new_vrf_id);
extern void zebra_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
#if CONFDATE > 20180823
CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
#endif
extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *) __attribute__((deprecated));

View File

@ -95,6 +95,8 @@ void nhrp_route_announce(int add, enum nhrp_cache_type type, const struct prefix
memset(&api, 0, sizeof(api));
api.type = ZEBRA_ROUTE_NHRP;
api.safi = SAFI_UNICAST;
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.prefix = *p;
switch (type) {

View File

@ -337,6 +337,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;
@ -387,6 +388,7 @@ void ospf6_zebra_add_discard(struct ospf6_route *request)
if (!CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;
@ -420,6 +422,7 @@ void ospf6_zebra_delete_discard(struct ospf6_route *request)
if (CHECK_FLAG(request->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = *dest;

View File

@ -389,6 +389,7 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@ -466,6 +467,7 @@ void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@ -487,6 +489,7 @@ void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p)
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;
@ -506,6 +509,7 @@ void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p)
memset(&api, 0, sizeof(api));
api.vrf_id = ospf->vrf_id;
api.nh_vrf_id = ospf->vrf_id;
api.type = ZEBRA_ROUTE_OSPF;
api.instance = ospf->instance;
api.safi = SAFI_UNICAST;

View File

@ -48,6 +48,7 @@ static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIP;
api.safi = SAFI_UNICAST;

View File

@ -48,6 +48,7 @@ static void ripng_zebra_ipv6_send(struct route_node *rp, u_char cmd)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_RIPNG;
api.safi = SAFI_UNICAST;
api.prefix = rp->p;

View File

@ -159,6 +159,7 @@ void route_add(struct prefix *p, struct nexthop *nh)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));
@ -180,6 +181,7 @@ void route_delete(struct prefix *p)
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
api.nh_vrf_id = VRF_DEFAULT;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
memcpy(&api.prefix, p, sizeof(*p));

View File

@ -238,10 +238,12 @@ void connected_up(struct interface *ifp, struct connected *ifc)
break;
}
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ifp->vrf_id,
ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ifp->vrf_id,
ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {

View File

@ -1048,7 +1048,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0);
else
@ -1096,7 +1096,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
rib_add(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, 0, 0, 0);
else

View File

@ -300,6 +300,13 @@ int main(int argc, char **argv)
zebra_if_init();
zebra_debug_init();
router_id_cmd_init();
/*
* Initialize NS( and implicitly the VRF module), and make kernel
* routing socket. */
zebra_ns_init();
zebra_vty_init();
access_list_init();
prefix_list_init();
#if defined(HAVE_RTADV)
@ -317,16 +324,6 @@ int main(int argc, char **argv)
/* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
/* Initialize NS( and implicitly the VRF module), and make kernel
* routing socket. */
zebra_ns_init();
/*
* Initialize show/config command after the vrf initialization is
* complete
*/
zebra_vty_init();
#if defined(HANDLE_ZAPI_FUZZING)
if (fuzzing) {
zserv_read_file(fuzzing);

View File

@ -59,6 +59,7 @@ struct route_entry {
/* VRF identifier. */
vrf_id_t vrf_id;
vrf_id_t nh_vrf_id;
/* Which routing table */
uint32_t table;
@ -293,8 +294,8 @@ extern void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
/* NOTE:
* All rib_add function will not just add prefix into RIB, but
* 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,
extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
int type, u_short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
u_int32_t table_id, u_int32_t metric, u_int32_t mtu,
uint8_t distance, route_tag_t tag);
@ -439,6 +440,8 @@ DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason),
extern void zebra_vty_init(void);
extern int static_config(struct vty *vty, struct zebra_vrf *zvrf,
afi_t afi, safi_t safi, const char *cmd);
extern pid_t pid;
#endif /*_ZEBRA_RIB_H */

View File

@ -403,6 +403,9 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
afi = AFI_IP6;
if (h->nlmsg_type == RTM_NEWROUTE) {
struct interface *ifp;
vrf_id_t nh_vrf_id = vrf_id;
if (!tb[RTA_MULTIPATH]) {
struct nexthop nh;
size_t sz = (afi == AFI_IP) ? 4 : 16;
@ -434,7 +437,14 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
if (gate)
memcpy(&nh.gate, gate, sz);
rib_add(afi, SAFI_UNICAST, vrf_id, proto,
if (index) {
ifp = if_lookup_by_index(index,
VRF_UNKNOWN);
if (ifp)
nh_vrf_id = ifp->vrf_id;
}
rib_add(afi, SAFI_UNICAST, vrf_id, nh_vrf_id, proto,
0, flags, &p, NULL, &nh, table, metric,
mtu, distance, tag);
} else {
@ -453,6 +463,7 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
re->metric = metric;
re->mtu = mtu;
re->vrf_id = vrf_id;
re->nh_vrf_id = vrf_id;
re->table = table;
re->nexthop_num = 0;
re->uptime = time(NULL);
@ -464,6 +475,18 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
break;
index = rtnh->rtnh_ifindex;
if (index) {
/*
* Yes we are looking this up
* for every nexthop and just
* using the last one looked
* up right now
*/
ifp = if_lookup_by_index(index,
VRF_UNKNOWN);
if (ifp)
re->nh_vrf_id = ifp->vrf_id;
}
gate = 0;
if (rtnh->rtnh_len > sizeof(*rtnh)) {
memset(tb, 0, sizeof(tb));
@ -940,10 +963,17 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
/*
* We have the ifindex so we should always send it
* This is especially useful if we are doing route
* leaking.
*/
if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
if (nexthop->type == NEXTHOP_TYPE_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
if (cmd == RTM_NEWROUTE) {
if (nexthop->rmap_src.ipv4.s_addr)
addattr_l(nlmsg, req_size, RTA_PREFSRC,
@ -961,8 +991,6 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
}
if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
if (cmd == RTM_NEWROUTE) {
if (!IN6_IS_ADDR_UNSPECIFIED(&nexthop->rmap_src.ipv6))
addattr_l(nlmsg, req_size, RTA_PREFSRC,
@ -1141,11 +1169,18 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
routedesc, inet6_ntoa(nexthop->gate.ipv6),
label_buf, nexthop->ifindex);
}
/*
* We have figured out the ifindex so we should always send it
* This is especially useful if we are doing route
* leaking.
*/
if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
rtnh->rtnh_ifindex = nexthop->ifindex;
/* ifindex */
if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
|| nexthop->type == NEXTHOP_TYPE_IFINDEX) {
rtnh->rtnh_ifindex = nexthop->ifindex;
if (nexthop->rmap_src.ipv4.s_addr)
*src = &nexthop->rmap_src;
else if (nexthop->src.ipv4.s_addr)
@ -1157,8 +1192,6 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
"nexthop via if %u",
routedesc, nexthop->ifindex);
} else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
rtnh->rtnh_ifindex = nexthop->ifindex;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"netlink_route_multipath() (%s): "

View File

@ -97,8 +97,9 @@ static void handle_route_entry(mib2_ipRouteEntry_t *routeEntry)
nh.type = NEXTHOP_TYPE_IPV4;
nh.gate.ipv4.s_addr = routeEntry->ipRouteNextHop;
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
zebra_flags, &prefix, NULL, &nh, 0, 0, 0, 0, 0);
rib_add(AFI_IP, SAFI_UNICAST, VRF_DEFAULT, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &prefix, NULL,
&nh, 0, 0, 0, 0, 0);
}
void route_read(struct zebra_ns *zns)

View File

@ -256,7 +256,7 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
if (src)
nexthop->src.ipv4 = *src;
nexthop->ifindex = ifindex;
ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
/*Pending: need to think if null ifp here is ok during bootup?
There was a crash because ifp here was coming to be NULL */
if (ifp)
@ -403,7 +403,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
if (set) {
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE);
zebra_deregister_rnh_static_nexthops(re->vrf_id,
zebra_deregister_rnh_static_nexthops(re->nh_vrf_id,
nexthop->resolved, top);
nexthops_free(nexthop->resolved);
nexthop->resolved = NULL;
@ -422,7 +422,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
* address in the routing table.
*/
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
if (ifp && connected_is_unnumbered(ifp)) {
if (if_is_operative(ifp))
return 1;
@ -450,7 +450,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
break;
}
/* Lookup table. */
table = zebra_vrf_table(afi, SAFI_UNICAST, re->vrf_id);
table = zebra_vrf_table(afi, SAFI_UNICAST, re->nh_vrf_id);
if (!table)
return 0;
@ -838,7 +838,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
family = 0;
switch (nexthop->type) {
case NEXTHOP_TYPE_IFINDEX:
ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
ifp = if_lookup_by_index(nexthop->ifindex, re->nh_vrf_id);
if (ifp && if_is_operative(ifp))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else
@ -866,7 +866,8 @@ static unsigned nexthop_active_check(struct route_node *rn,
if (rn->p.family != AF_INET)
family = AFI_IP6;
if (IN6_IS_ADDR_LINKLOCAL(&nexthop->gate.ipv6)) {
ifp = if_lookup_by_index(nexthop->ifindex, re->vrf_id);
ifp = if_lookup_by_index(nexthop->ifindex,
re->nh_vrf_id);
if (ifp && if_is_operative(ifp))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else
@ -909,7 +910,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr));
/* It'll get set if required inside */
ret = zebra_route_map_check(family, re->type, p, nexthop, re->vrf_id,
ret = zebra_route_map_check(family, re->type, p, nexthop, re->nh_vrf_id,
re->tag);
if (ret == RMAP_DENYMATCH) {
if (IS_ZEBRA_DEBUG_RIB) {
@ -917,7 +918,8 @@ static unsigned nexthop_active_check(struct route_node *rn,
zlog_debug(
"%u:%s: Filtering out with NH out %s due to route map",
re->vrf_id, buf,
ifindex2ifname(nexthop->ifindex, re->vrf_id));
ifindex2ifname(nexthop->ifindex,
re->nh_vrf_id));
}
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
}
@ -2502,9 +2504,10 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}
int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
int flags, struct prefix *p, struct prefix_ipv6 *src_p,
const struct nexthop *nh, u_int32_t table_id, u_int32_t metric,
int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, vrf_id_t nh_vrf_id,
int type, u_short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
u_int32_t table_id, u_int32_t metric,
u_int32_t mtu, uint8_t distance, route_tag_t tag)
{
struct route_entry *re;
@ -2520,6 +2523,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, u_short instance,
re->mtu = mtu;
re->table = table_id;
re->vrf_id = vrf_id;
re->nh_vrf_id = nh_vrf_id;
re->nexthop_num = 0;
re->uptime = time(NULL);
re->tag = tag;

View File

@ -951,6 +951,8 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
state->type = re->type;
state->distance = re->distance;
state->metric = re->metric;
state->vrf_id = re->vrf_id;
state->nh_vrf_id = re->vrf_id;
route_entry_copy_nexthops(state, re->nexthop);
rnh->state = state;

View File

@ -1329,7 +1329,7 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto,
struct nh_rmap_obj nh_obj;
nh_obj.nexthop = nexthop;
nh_obj.vrf_id = re->vrf_id;
nh_obj.vrf_id = re->nh_vrf_id;
nh_obj.source_protocol = re->type;
nh_obj.metric = re->metric;
nh_obj.tag = re->tag;

View File

@ -91,7 +91,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET;
nh_p.prefixlen = IPV4_MAX_BITLEN;
nh_p.u.prefix4 = si->addr.ipv4;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV4_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv4_ifindex_add(
@ -111,7 +111,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET6;
nh_p.prefixlen = IPV6_MAX_BITLEN;
nh_p.u.prefix6 = si->addr.ipv6;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV6_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
@ -141,7 +141,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
*/
if (si->type == STATIC_IPV4_GATEWAY
|| si->type == STATIC_IPV6_GATEWAY)
zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
RNH_NEXTHOP_TYPE, &nh_p);
else
rib_queue_add(rn);
@ -155,6 +155,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
re->metric = 0;
re->mtu = 0;
re->vrf_id = si->vrf_id;
re->nh_vrf_id = si->nh_vrf_id;
re->table =
(si->vrf_id != VRF_DEFAULT)
? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id
@ -169,7 +170,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET;
nh_p.prefixlen = IPV4_MAX_BITLEN;
nh_p.u.prefix4 = si->addr.ipv4;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV4_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv4_ifindex_add(
@ -189,7 +190,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
nh_p.family = AF_INET6;
nh_p.prefixlen = IPV6_MAX_BITLEN;
nh_p.u.prefix6 = si->addr.ipv6;
zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
zebra_register_rnh_static_nh(si->nh_vrf_id, &nh_p, rn);
break;
case STATIC_IPV6_GATEWAY_IFNAME:
nexthop = route_entry_nexthop_ipv6_ifindex_add(
@ -221,7 +222,7 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
if (si->type == STATIC_IPV4_GATEWAY
|| si->type == STATIC_IPV6_GATEWAY) {
rib_addnode(rn, re, 0);
zebra_evaluate_rnh(si->vrf_id, nh_p.family, 1,
zebra_evaluate_rnh(si->nh_vrf_id, nh_p.family, 1,
RNH_NEXTHOP_TYPE, &nh_p);
} else
rib_addnode(rn, re, 1);
@ -378,6 +379,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
struct prefix_ipv6 *src_p, union g_addr *gate,
const char *ifname, enum static_blackhole_type bh_type,
route_tag_t tag, u_char distance, struct zebra_vrf *zvrf,
struct zebra_vrf *nh_zvrf,
struct static_nh_label *snh_label)
{
struct route_node *rn;
@ -439,6 +441,8 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
si->bh_type = bh_type;
si->tag = tag;
si->vrf_id = zvrf_id(zvrf);
si->nh_vrf_id = zvrf_id(nh_zvrf);
if (ifname)
strlcpy(si->ifname, ifname, sizeof(si->ifname));
si->ifindex = IFINDEX_INTERNAL;
@ -493,7 +497,7 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
else {
struct interface *ifp;
ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
ifp = if_lookup_by_name(ifname, zvrf_id(nh_zvrf));
if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
si->ifindex = ifp->ifindex;
static_install_route(afi, safi, p, src_p, si);

View File

@ -54,6 +54,7 @@ struct static_route {
/* VRF identifier. */
vrf_id_t vrf_id;
vrf_id_t nh_vrf_id;
/* Administrative distance. */
u_char distance;
@ -89,6 +90,7 @@ extern int static_add_route(afi_t, safi_t safi, u_char type, struct prefix *p,
const char *ifname,
enum static_blackhole_type bh_type, route_tag_t tag,
u_char distance, struct zebra_vrf *zvrf,
struct zebra_vrf *nh_zvrf,
struct static_nh_label *snh_label);
extern int static_delete_route(afi_t, safi_t safi, u_char type,

View File

@ -476,13 +476,19 @@ static int vrf_config_write(struct vty *vty)
if (!zvrf)
continue;
if (strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
if (vrf->vrf_id != VRF_DEFAULT)
vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
if (zvrf->l3vni)
static_config(vty, zvrf, AFI_IP, SAFI_UNICAST, "ip route");
static_config(vty, zvrf, AFI_IP, SAFI_MULTICAST, "ip mroute");
static_config(vty, zvrf, AFI_IP6, SAFI_UNICAST, "ipv6 route");
if (vrf->vrf_id != VRF_DEFAULT && zvrf->l3vni)
vty_out(vty, " vni %u\n", zvrf->l3vni);
if (vrf->vrf_id != VRF_DEFAULT)
vty_out(vty, "!\n");
}
}
return 0;
}

View File

@ -78,12 +78,15 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
#define CMD_VNI_RANGE "(1-16777215)"
/* General function for static route. */
static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
static int zebra_static_route_leak(struct vty *vty,
struct zebra_vrf *zvrf,
struct zebra_vrf *nh_zvrf,
afi_t afi, safi_t safi,
const char *negate, const char *dest_str,
const char *mask_str, const char *src_str,
const char *gate_str, const char *ifname,
const char *flag_str, const char *tag_str,
const char *distance_str, const char *vrf_id_str,
const char *distance_str,
const char *label_str)
{
int ret;
@ -95,7 +98,6 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
struct in_addr mask;
enum static_blackhole_type bh_type = 0;
route_tag_t tag = 0;
struct zebra_vrf *zvrf;
u_char type;
struct static_nh_label snh_label;
@ -145,14 +147,6 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
if (tag_str)
tag = strtoul(tag_str, NULL, 10);
/* VRF id */
zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
if (!zvrf) {
vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
return CMD_WARNING_CONFIG_FAILED;
}
/* Labels */
memset(&snh_label, 0, sizeof(struct static_nh_label));
if (label_str) {
@ -239,7 +233,8 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
if (!negate)
static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
bh_type, tag, distance, zvrf, &snh_label);
bh_type, tag, distance, zvrf, nh_zvrf,
&snh_label);
else
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
tag, distance, zvrf, &snh_label);
@ -247,6 +242,31 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
return CMD_SUCCESS;
}
static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
const char *negate, const char *dest_str,
const char *mask_str, const char *src_str,
const char *gate_str, const char *ifname,
const char *flag_str, const char *tag_str,
const char *distance_str, const char *vrf_id_str,
const char *label_str)
{
struct zebra_vrf *zvrf;
/* VRF id */
zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
if (!zvrf) {
vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, zvrf, afi, safi,
negate, dest_str, mask_str, src_str,
gate_str, ifname, flag_str, tag_str,
distance_str, label_str);
}
/* Static unicast routes for multicast RPF lookup. */
DEFPY (ip_mroute_dist,
ip_mroute_dist_cmd,
@ -387,6 +407,37 @@ DEFPY(ip_route_blackhole,
tag_str, distance_str, vrf, label);
}
DEFPY(ip_route_blackhole_vrf,
ip_route_blackhole_vrf_cmd,
"[no] ip route\
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
<reject|blackhole>$flag \
[{ \
tag (1-4294967295) \
|(1-255)$distance \
|label WORD \
}]",
NO_STR IP_STR
"Establish static routes\n"
"IP destination prefix (e.g. 10.0.0.0/8)\n"
"IP destination prefix\n"
"IP destination prefix mask\n"
"Emit an ICMP unreachable when matched\n"
"Silently discard pkts when matched\n"
"Set tag for this route\n"
"Tag value\n"
"Distance value for this route\n"
MPLS_LABEL_HELPSTR)
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct zebra_vrf *zvrf = vrf->info;
return zebra_static_route_leak(vty, zvrf, zvrf,
AFI_IP, SAFI_UNICAST, no, prefix,
mask_str, NULL, NULL, NULL, flag,
tag_str, distance_str, label);
}
DEFPY(ip_route_address_interface,
ip_route_address_interface_cmd,
"[no] ip route\
@ -398,6 +449,7 @@ DEFPY(ip_route_address_interface,
|(1-255)$distance \
|vrf NAME \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
@ -411,16 +463,85 @@ DEFPY(ip_route_address_interface,
"Tag value\n"
"Distance value for this route\n"
VRF_CMD_HELP_STR
MPLS_LABEL_HELPSTR)
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
struct zebra_vrf *zvrf;
struct zebra_vrf *nh_zvrf;
const char *flag = NULL;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
zvrf = zebra_vrf_lookup_by_name(vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP, SAFI_UNICAST, no, prefix,
mask_str, NULL, gate_str, ifname, flag,
tag_str, distance_str, vrf, label);
tag_str, distance_str, label);
}
DEFPY(ip_route_address_interface_vrf,
ip_route_address_interface_vrf_cmd,
"[no] ip route\
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
A.B.C.D$gate \
INTERFACE$ifname \
[{ \
tag (1-4294967295) \
|(1-255)$distance \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
"IP destination prefix (e.g. 10.0.0.0/8)\n"
"IP destination prefix\n"
"IP destination prefix mask\n"
"IP gateway address\n"
"IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
null route.\n"
"Set tag for this route\n"
"Tag value\n"
"Distance value for this route\n"
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
const char *flag = NULL;
struct zebra_vrf *zvrf = vrf->info;
struct zebra_vrf *nh_zvrf;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP, SAFI_UNICAST, no, prefix,
mask_str, NULL, gate_str, ifname, flag,
tag_str, distance_str, label);
}
DEFPY(ip_route,
@ -433,6 +554,7 @@ DEFPY(ip_route,
|(1-255)$distance \
|vrf NAME \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
@ -445,16 +567,83 @@ DEFPY(ip_route,
"Tag value\n"
"Distance value for this route\n"
VRF_CMD_HELP_STR
MPLS_LABEL_HELPSTR)
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
struct zebra_vrf *zvrf;
struct zebra_vrf *nh_zvrf;
const char *flag = NULL;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
zvrf = zebra_vrf_lookup_by_name(vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP, SAFI_UNICAST, no, prefix,
mask_str, NULL, gate_str, ifname, flag,
tag_str, distance_str, label);
}
DEFPY(ip_route_vrf,
ip_route_vrf_cmd,
"[no] ip route\
<A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
<A.B.C.D$gate|INTERFACE$ifname> \
[{ \
tag (1-4294967295) \
|(1-255)$distance \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
"IP destination prefix (e.g. 10.0.0.0/8)\n"
"IP destination prefix\n"
"IP destination prefix mask\n"
"IP gateway address\n"
"IP gateway interface name\n"
"Set tag for this route\n"
"Tag value\n"
"Distance value for this route\n"
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct zebra_vrf *zvrf = vrf->info;
struct zebra_vrf *nh_zvrf;
const char *flag = NULL;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP, SAFI_UNICAST, no, prefix,
mask_str, NULL, gate_str, ifname, flag,
tag_str, distance_str, vrf, label);
tag_str, distance_str, label);
}
/* New RIB. Detailed information for IPv4 route. */
@ -539,7 +728,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", via %s",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@ -549,12 +738,12 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", via %s",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty, " directly connected, %s",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
vty_out(vty, " unreachable");
@ -576,6 +765,14 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
default:
break;
}
if (re->vrf_id != re->nh_vrf_id) {
struct vrf *vrf =
vrf_lookup_by_id(re->nh_vrf_id);
vty_out(vty, "(vrf %s)", vrf->name);
}
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
vty_out(vty, " (duplicate nexthop removed)");
@ -715,7 +912,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
}
break;
case NEXTHOP_TYPE_IPV6:
@ -734,7 +931,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
}
break;
@ -747,7 +944,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
json_object_boolean_true_add(json_nexthop,
@ -774,6 +971,14 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
break;
}
if (re->nh_vrf_id != re->vrf_id) {
struct vrf *vrf =
vrf_lookup_by_id(re->nh_vrf_id);
json_object_string_add(json_nexthop,
"vrf",
vrf->name);
}
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
json_object_boolean_true_add(json_nexthop,
"duplicate");
@ -881,7 +1086,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", %s",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@ -891,12 +1096,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", %s",
ifindex2ifname(nexthop->ifindex,
re->vrf_id));
re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty, " is directly connected, %s",
ifindex2ifname(nexthop->ifindex, re->vrf_id));
ifindex2ifname(nexthop->ifindex,
re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
vty_out(vty, " unreachable");
@ -917,6 +1123,14 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
default:
break;
}
if (re->nh_vrf_id != re->vrf_id) {
struct vrf *vrf =
vrf_lookup_by_id(re->nh_vrf_id);
vty_out(vty, "(vrf %s)", vrf->name);
}
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
vty_out(vty, " inactive");
@ -1603,26 +1817,26 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
}
/* Write static route configuration. */
static int static_config(struct vty *vty, afi_t afi, safi_t safi,
const char *cmd)
int static_config(struct vty *vty, struct zebra_vrf *zvrf,
afi_t afi, safi_t safi, const char *cmd)
{
char spacing[100];
struct route_node *rn;
struct static_route *si;
struct route_table *stable;
struct vrf *vrf;
struct zebra_vrf *zvrf;
char buf[SRCDEST2STR_BUFFER];
int write = 0;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if (!(zvrf = vrf->info))
continue;
if ((stable = zvrf->stable[afi][safi]) == NULL)
continue;
return write;
sprintf(spacing, "%s%s",
(zvrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ",
cmd);
for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
for (si = rn->info; si; si = si->next) {
vty_out(vty, "%s %s", cmd,
vty_out(vty, "%s %s", spacing,
srcdest_rnode2str(rn, buf, sizeof buf));
switch (si->type) {
@ -1676,16 +1890,18 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
!= ZEBRA_STATIC_DISTANCE_DEFAULT)
vty_out(vty, " %d", si->distance);
if (si->vrf_id != VRF_DEFAULT)
vty_out(vty, " vrf %s",
zvrf_name(zvrf));
if (si->nh_vrf_id != si->vrf_id) {
struct vrf *vrf;
vrf = vrf_lookup_by_id(si->nh_vrf_id);
vty_out(vty, " nexthop-vrf %s",
(vrf) ? vrf->name : "Unknown");
}
/* Label information */
if (si->snh_label.num_labels)
vty_out(vty, " label %s",
mpls_label2str(
si->snh_label
.num_labels,
mpls_label2str(si->snh_label.num_labels,
si->snh_label.label,
buf, sizeof buf, 0));
@ -1693,7 +1909,6 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
write = 1;
}
}
return write;
}
@ -1727,6 +1942,38 @@ DEFPY(ipv6_route_blackhole,
tag_str, distance_str, vrf, label);
}
DEFPY(ipv6_route_blackhole_vrf,
ipv6_route_blackhole_vrf_cmd,
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
<Null0|reject|blackhole>$flag \
[{ \
tag (1-4294967295) \
|(1-255)$distance \
|label WORD \
}]",
NO_STR
IPV6_STR
"Establish static routes\n"
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
"IPv6 source-dest route\n"
"IPv6 source prefix\n"
"Null interface\n"
"Emit an ICMP unreachable when matched\n"
"Silently discard pkts when matched\n"
"Set tag for this route\n"
"Tag value\n"
"Distance value for this prefix\n"
MPLS_LABEL_HELPSTR)
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct zebra_vrf *zvrf = vrf->info;
return zebra_static_route_leak(vty, zvrf, zvrf,
AFI_IP6, SAFI_UNICAST, no, prefix_str,
NULL, from_str, NULL, NULL, flag,
tag_str, distance_str, label);
}
DEFPY(ipv6_route_address_interface,
ipv6_route_address_interface_cmd,
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
@ -1737,6 +1984,7 @@ DEFPY(ipv6_route_address_interface,
|(1-255)$distance \
|vrf NAME \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
@ -1750,11 +1998,72 @@ DEFPY(ipv6_route_address_interface,
"Tag value\n"
"Distance value for this prefix\n"
VRF_CMD_HELP_STR
MPLS_LABEL_HELPSTR)
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
struct zebra_vrf *zvrf;
struct zebra_vrf *nh_zvrf;
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
zvrf = zebra_vrf_lookup_by_name(vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP6, SAFI_UNICAST, no, prefix_str,
NULL, from_str, gate_str, ifname, NULL,
tag_str, distance_str, vrf, label);
tag_str, distance_str, label);
}
DEFPY(ipv6_route_address_interface_vrf,
ipv6_route_address_interface_vrf_cmd,
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
X:X::X:X$gate \
INTERFACE$ifname \
[{ \
tag (1-4294967295) \
|(1-255)$distance \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
"Establish static routes\n"
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
"IPv6 source-dest route\n"
"IPv6 source prefix\n"
"IPv6 gateway address\n"
"IPv6 gateway interface name\n"
"Set tag for this route\n"
"Tag value\n"
"Distance value for this prefix\n"
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct zebra_vrf *zvrf = vrf->info;
struct zebra_vrf *nh_zvrf;
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP6, SAFI_UNICAST, no, prefix_str,
NULL, from_str, gate_str, ifname, NULL,
tag_str, distance_str, label);
}
DEFPY(ipv6_route,
@ -1766,6 +2075,7 @@ DEFPY(ipv6_route,
|(1-255)$distance \
|vrf NAME \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
@ -1779,11 +2089,71 @@ DEFPY(ipv6_route,
"Tag value\n"
"Distance value for this prefix\n"
VRF_CMD_HELP_STR
MPLS_LABEL_HELPSTR)
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
struct zebra_vrf *zvrf;
struct zebra_vrf *nh_zvrf;
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
zvrf = zebra_vrf_lookup_by_name(vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP6, SAFI_UNICAST, no, prefix_str,
NULL, from_str, gate_str, ifname, NULL,
tag_str, distance_str, vrf, label);
tag_str, distance_str, label);
}
DEFPY(ipv6_route_vrf,
ipv6_route_vrf_cmd,
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
<X:X::X:X$gate|INTERFACE$ifname> \
[{ \
tag (1-4294967295) \
|(1-255)$distance \
|label WORD \
|nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
"Establish static routes\n"
"IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
"IPv6 source-dest route\n"
"IPv6 source prefix\n"
"IPv6 gateway address\n"
"IPv6 gateway interface name\n"
"Set tag for this route\n"
"Tag value\n"
"Distance value for this prefix\n"
MPLS_LABEL_HELPSTR
VRF_CMD_HELP_STR)
{
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct zebra_vrf *zvrf = vrf->info;
struct zebra_vrf *nh_zvrf;
nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
if (!nh_zvrf) {
vty_out(vty, "%% nexthop vrf %s is not defined\n",
nexthop_vrf);
return CMD_WARNING_CONFIG_FAILED;
}
return zebra_static_route_leak(vty, zvrf, nh_zvrf,
AFI_IP6, SAFI_UNICAST, no, prefix_str,
NULL, from_str, gate_str, ifname, NULL,
tag_str, distance_str, label);
}
/*
@ -2419,11 +2789,8 @@ static int zebra_ip_config(struct vty *vty)
{
int write = 0;
write += static_config(vty, AFI_IP, SAFI_UNICAST, "ip route");
write += static_config(vty, AFI_IP, SAFI_MULTICAST, "ip mroute");
write += static_config(vty, AFI_IP6, SAFI_UNICAST, "ipv6 route");
write += zebra_import_table_config(vty);
return write;
}
@ -2859,8 +3226,11 @@ void zebra_vty_init(void)
install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
install_element(CONFIG_NODE, &ip_route_cmd);
install_element(VRF_NODE, &ip_route_vrf_cmd);
install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
@ -2882,8 +3252,11 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
install_element(CONFIG_NODE, &ipv6_route_cmd);
install_element(VRF_NODE, &ipv6_route_vrf_cmd);
install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);

View File

@ -592,6 +592,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p,
memset(&api, 0, sizeof(api));
api.vrf_id = re->vrf_id;
api.nh_vrf_id = re->nh_vrf_id;
api.type = re->type;
api.instance = re->instance;
api.flags = re->flags;
@ -1136,6 +1137,7 @@ static int zread_route_add(struct zserv *client, u_short length,
re->flags = api.flags;
re->uptime = time(NULL);
re->vrf_id = vrf_id;
re->nh_vrf_id = api.nh_vrf_id;
re->table = zvrf->table_id;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
@ -1362,6 +1364,7 @@ static int zread_ipv4_add(struct zserv *client, u_short length,
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
re->nh_vrf_id = zvrf_id(zvrf);
/* Nexthop parse. */
if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) {
@ -1571,6 +1574,7 @@ static int zread_ipv4_route_ipv6_nexthop_add(struct zserv *client,
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
re->nh_vrf_id = zvrf_id(zvrf);
/* We need to give nh-addr, nh-ifindex with the same next-hop object
* to the re to ensure that IPv6 multipathing works; need to coalesce
@ -1856,6 +1860,8 @@ static int zread_ipv6_add(struct zserv *client, u_short length,
/* VRF ID */
re->vrf_id = zvrf_id(zvrf);
re->nh_vrf_id = zvrf_id(zvrf);
re->table = zvrf->table_id;
ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re);