From c423229b54f01bbc7522a2d5c73221db8ebbecf0 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Thu, 24 Nov 2016 17:10:19 +0100 Subject: [PATCH] zebra: support static srcdest routes Signed-off-by: Christian Franke --- zebra/zebra_mpls_vty.c | 32 ++--- zebra/zebra_static.c | 27 +++-- zebra/zebra_static.h | 9 +- zebra/zebra_vrf.c | 30 +++-- zebra/zebra_vty.c | 259 +++++++++++++++++++++++++++++++++-------- 5 files changed, 260 insertions(+), 97 deletions(-) diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index 0185b555f2..fcd0fff32c 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -521,7 +521,7 @@ DEFUN (ipv6_route_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, NULL, NULL, NULL, NULL, NULL, argv[5]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, NULL, NULL, NULL, argv[5]->arg); } DEFUN (ipv6_route_tag_label, @@ -537,7 +537,7 @@ DEFUN (ipv6_route_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, NULL, NULL, argv[5]->arg, NULL, NULL, argv[7]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, argv[5]->arg, NULL, NULL, argv[7]->arg); } DEFUN (ipv6_route_ifname_label, @@ -551,7 +551,7 @@ DEFUN (ipv6_route_ifname_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, NULL, argv[6]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, NULL, argv[6]->arg); } DEFUN (ipv6_route_ifname_tag_label, ipv6_route_ifname_tag_label_cmd, @@ -566,7 +566,7 @@ DEFUN (ipv6_route_ifname_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); } DEFUN (ipv6_route_pref_label, @@ -581,7 +581,7 @@ DEFUN (ipv6_route_pref_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, NULL, NULL, NULL, argv[4]->arg, NULL, argv[6]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, NULL, argv[4]->arg, NULL, argv[6]->arg); } DEFUN (ipv6_route_pref_tag_label, @@ -598,7 +598,7 @@ DEFUN (ipv6_route_pref_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, NULL, NULL, argv[5]->arg, argv[6]->arg, NULL, argv[8]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, NULL, NULL, argv[5]->arg, argv[6]->arg, NULL, argv[8]->arg); } DEFUN (ipv6_route_ifname_pref_label, @@ -613,7 +613,7 @@ DEFUN (ipv6_route_ifname_pref_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); } DEFUN (ipv6_route_ifname_pref_tag_label, @@ -630,7 +630,7 @@ DEFUN (ipv6_route_ifname_pref_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 1, argv[2]->arg, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); + return static_ipv6_func (vty, 1, argv[2]->arg, NULL, argv[3]->arg, argv[4]->arg, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); } DEFUN (no_ipv6_route_label, @@ -645,7 +645,7 @@ DEFUN (no_ipv6_route_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, NULL, NULL, argv[6]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, NULL, NULL, NULL, argv[6]->arg); } DEFUN (no_ipv6_route_tag_label, @@ -662,7 +662,7 @@ DEFUN (no_ipv6_route_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, NULL, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, argv[6]->arg, NULL, NULL, argv[8]->arg); } DEFUN (no_ipv6_route_ifname_label, @@ -677,7 +677,7 @@ DEFUN (no_ipv6_route_ifname_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, NULL, NULL, NULL, argv[7]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, NULL, NULL, NULL, argv[7]->arg); } DEFUN (no_ipv6_route_ifname_tag_label, @@ -694,7 +694,7 @@ DEFUN (no_ipv6_route_ifname_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, NULL, NULL, argv[9]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, NULL, NULL, argv[9]->arg); } DEFUN (no_ipv6_route_pref_label, @@ -710,7 +710,7 @@ DEFUN (no_ipv6_route_pref_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, NULL, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, NULL, argv[5]->arg, NULL, argv[7]->arg); } DEFUN (no_ipv6_route_pref_tag_label, @@ -728,7 +728,7 @@ DEFUN (no_ipv6_route_pref_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, NULL, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, NULL, NULL, argv[6]->arg, argv[7]->arg, NULL, argv[9]->arg); } DEFUN (no_ipv6_route_ifname_pref_label, @@ -744,7 +744,7 @@ DEFUN (no_ipv6_route_ifname_pref_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, NULL, argv[6]->arg, NULL, argv[8]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, NULL, argv[6]->arg, NULL, argv[8]->arg); } DEFUN (no_ipv6_route_ifname_pref_tag_label, @@ -762,7 +762,7 @@ DEFUN (no_ipv6_route_ifname_pref_tag_label, "Specify label(s) for this route\n" "One or more labels separated by '/'\n") { - return static_ipv6_func (vty, 0, argv[3]->arg, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, argv[8]->arg, NULL, argv[10]->arg); + return static_ipv6_func (vty, 0, argv[3]->arg, NULL, argv[4]->arg, argv[5]->arg, NULL, argv[7]->arg, argv[8]->arg, NULL, argv[10]->arg); } /* MPLS LSP configuration write function. */ diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 33f0a2bd72..1302f1cd39 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -24,6 +24,7 @@ #include #include +#include #include "vty.h" #include "zebra/debug.h" @@ -37,7 +38,8 @@ /* Install static route into rib. */ void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) +static_install_route (afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si) { struct rib *rib; struct route_node *rn; @@ -53,7 +55,7 @@ static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ro memset (&nh_p, 0, sizeof (nh_p)); /* Lookup existing route */ - rn = route_node_get (table, p); + rn = srcdest_rnode_get (table, p, src_p); RNODE_FOREACH_RIB (rn, rib) { if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) @@ -252,7 +254,8 @@ static_nexthop_same (struct nexthop *nexthop, struct static_route *si) /* Uninstall static route from RIB. */ void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si) +static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si) { struct route_node *rn; struct rib *rib; @@ -266,7 +269,7 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ return; /* Lookup existing route with type and distance. */ - rn = route_node_lookup (table, p); + rn = srcdest_rnode_lookup (table, p, src_p); if (! rn) return; @@ -328,13 +331,13 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ rib_install_kernel (rn, rib, rib); /* Update redistribution if it's selected */ if (CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED)) - redistribute_update (&rn->p, NULL, rib, NULL); + redistribute_update (p, (struct prefix*)src_p, rib, NULL); } else { /* Remove from redistribute if selected route becomes inactive */ if (CHECK_FLAG(rib->flags, ZEBRA_FLAG_SELECTED)) - redistribute_delete (&rn->p, NULL, rib); + redistribute_delete (p, (struct prefix*)src_p, rib); /* Remove from kernel if fib route becomes inactive */ if (CHECK_FLAG(rib->status, RIB_ENTRY_SELECTED_FIB)) rib_uninstall_kernel (rn, rib); @@ -364,6 +367,7 @@ static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_ 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, ifindex_t ifindex, const char *ifname, u_char flags, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, @@ -391,7 +395,7 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, return -1; /* Lookup static route prefix. */ - rn = route_node_get (stable, p); + rn = srcdest_rnode_get (stable, p, src_p); /* Do nothing if there is a same static route. */ for (si = rn->info; si; si = si->next) @@ -416,7 +420,7 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, /* Distance or tag or label changed, delete existing first. */ if (update) - static_delete_route (afi, safi, type, p, gate, ifindex, update->tag, + static_delete_route (afi, safi, type, p, src_p, gate, ifindex, update->tag, update->distance, zvrf, &update->snh_label); /* Make new static route structure. */ @@ -477,13 +481,14 @@ static_add_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, si->next = cp; /* Install into rib. */ - static_install_route (afi, safi, p, si); + static_install_route (afi, safi, p, src_p, si); return 1; } int static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, ifindex_t ifindex, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label) @@ -498,7 +503,7 @@ static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, return -1; /* Lookup static route prefix. */ - rn = route_node_lookup (stable, p); + rn = srcdest_rnode_lookup (stable, p, src_p); if (! rn) return 0; @@ -522,7 +527,7 @@ static_delete_route (afi_t afi, safi_t safi, u_char type, struct prefix *p, } /* Install into rib. */ - static_uninstall_route (afi, safi, p, si); + static_uninstall_route (afi, safi, p, src_p, si); /* Unlink static route from linked list. */ if (si->prev) diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 233436f02d..adc2efff58 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -83,12 +83,15 @@ struct static_route }; extern void -static_install_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); +static_install_route (afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si); extern void -static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, struct static_route *si); +static_uninstall_route (afi_t afi, safi_t safi, struct prefix *p, + struct prefix_ipv6 *src_p, struct static_route *si); extern int static_add_route (afi_t, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, ifindex_t ifindex, const char *ifname, u_char flags, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, @@ -96,6 +99,7 @@ static_add_route (afi_t, safi_t safi, u_char type, struct prefix *p, extern int static_delete_route (afi_t, safi_t safi, u_char type, struct prefix *p, + struct prefix_ipv6 *src_p, union g_addr *gate, ifindex_t ifindex, route_tag_t tag, u_char distance, struct zebra_vrf *zvrf, struct static_nh_label *snh_label); @@ -109,6 +113,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, int static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_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, diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index bc86e4a10b..6fc41c3a14 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -133,7 +133,7 @@ zebra_vrf_static_route_interface_fixup (struct interface *ifp) (si->ifindex != ifp->ifindex)) { si->ifindex = ifp->ifindex; - static_install_route (afi, safi, &rn->p, si); + static_install_route (afi, safi, &rn->p, NULL, si); } } } @@ -177,7 +177,7 @@ zebra_vrf_enable (struct vrf *vrf) else continue; } - static_install_route (afi, safi, &rn->p, si); + static_install_route (afi, safi, &rn->p, NULL, si); } } @@ -208,7 +208,7 @@ zebra_vrf_disable (struct vrf *vrf) for (rn = route_top (stable); rn; rn = route_next (rn)) for (si = rn->info; si; si = si->next) - static_uninstall_route(afi, safi, &rn->p, si); + static_uninstall_route(afi, safi, &rn->p, NULL, si); } return 0; @@ -344,8 +344,7 @@ zebra_rtable_node_cleanup (struct route_table *table, struct route_node *node) } static void -zebra_stable_node_destroy (route_table_delegate_t *delegate, - struct route_table *table, struct route_node *node) +zebra_stable_node_cleanup (struct route_table *table, struct route_node *node) { struct static_route *si, *next; @@ -355,8 +354,6 @@ zebra_stable_node_destroy (route_table_delegate_t *delegate, next = si->next; XFREE (MTYPE_STATIC_ROUTE, si); } - - route_node_destroy (delegate, table, node); } static void @@ -366,11 +363,6 @@ zebra_rnhtable_node_cleanup (struct route_table *table, struct route_node *node) zebra_free_rnh (node->info); } -route_table_delegate_t zebra_stable_delegate = { - .create_node = route_node_create, - .destroy_node = zebra_stable_node_destroy -}; - /* * Create a routing table for the specific AFI/SAFI in the given VRF. */ @@ -410,11 +402,15 @@ zebra_vrf_alloc (void) for (afi = AFI_IP; afi <= AFI_IP6; afi++) { for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) - { - zebra_vrf_table_create (zvrf, afi, safi); - zvrf->stable[afi][safi] = - route_table_init_with_delegate (&zebra_stable_delegate); - } + { + zebra_vrf_table_create (zvrf, afi, safi); + if (afi == AFI_IP6) + table = srcdest_table_init(); + else + table = route_table_init(); + table->cleanup = zebra_stable_node_cleanup; + zvrf->stable[afi][safi] = table; + } table = route_table_init(); table->cleanup = zebra_rnhtable_node_cleanup; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index bba0571c9e..17d8249906 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -142,10 +142,10 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, return CMD_WARNING; } if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, ifindex, ifname, + static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, + static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; } @@ -170,10 +170,10 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, if (gate_str == NULL) { if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, NULL, ifindex, ifname, flag, + static_add_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, ifname, flag, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex, tag, distance, + static_delete_route (AFI_IP, safi, type, &p, NULL, NULL, ifindex, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; @@ -199,11 +199,11 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, type = STATIC_IPV4_GATEWAY; if (add_cmd) - static_add_route (AFI_IP, safi, type, &p, + static_add_route (AFI_IP, safi, type, &p, NULL, ifindex ? NULL : (union g_addr *)&gate, ifindex, ifname, flag, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP, safi, type, &p, + static_delete_route (AFI_IP, safi, type, &p, NULL, ifindex ? NULL : (union g_addr *)&gate, ifindex, tag, distance, zvrf, &snh_label); @@ -2329,6 +2329,7 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) /* General fucntion for IPv6 static route. */ int static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_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, @@ -2336,7 +2337,8 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, { int ret; u_char distance; - struct prefix p; + struct prefix p, src; + struct prefix_ipv6 *src_p = NULL; struct in6_addr *gate = NULL; struct in6_addr gate_addr; u_char type = STATIC_BLACKHOLE; @@ -2354,6 +2356,17 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, return CMD_WARNING; } + if (src_str) + { + ret = str2prefix (src_str, &src); + if (ret <= 0 || src.family != AF_INET6) + { + vty_out (vty, "%% Malformed source address%s", VTY_NEWLINE); + return CMD_WARNING; + } + src_p = (struct prefix_ipv6*)&src; + } + /* Apply mask for given prefix. */ apply_mask (&p); @@ -2407,10 +2420,10 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, return CMD_WARNING; } if (add_cmd) - static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, NULL, ifindex, ifname, + static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, NULL, NULL, ifindex, ifname, ZEBRA_FLAG_BLACKHOLE, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, NULL, ifindex, tag, + static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, NULL, NULL, ifindex, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; } @@ -2474,10 +2487,10 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } if (add_cmd) - static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, (union g_addr *)gate, + static_add_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, ifindex, ifname, flag, tag, distance, zvrf, &snh_label); else - static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, (union g_addr *)gate, + static_delete_route (AFI_IP6, SAFI_UNICAST, type, &p, src_p, (union g_addr *)gate, ifindex, tag, distance, zvrf, &snh_label); return CMD_SUCCESS; @@ -2485,10 +2498,12 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, DEFUN (ipv6_route, ipv6_route_cmd, - "ipv6 route X:X::X:X/M [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "ipv6 route X:X::X:X/M [from X:X::X:X/M] [tag (1-4294967295)] [(1-255)] [vrf NAME]", IP_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" "Null interface\n" @@ -2501,15 +2516,29 @@ DEFUN (ipv6_route, "One or more labels separated by '/'\n") { int idx_ipv6_prefixlen = 2; - int idx_ipv6_ifname = 3; - int idx_curr = 4; - char *tag, *distance, *vrf; + int idx_ipv6_ifname; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[3]->text, "from")) + { + src = argv[4]->arg; + idx_ipv6_ifname = 5; + idx_curr = 6; + } + else + { + src = NULL; + idx_ipv6_ifname = 3; + idx_curr = 4; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 1, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6_ifname]->arg, NULL, NULL, tag, distance, vrf, NULL); @@ -2517,10 +2546,12 @@ DEFUN (ipv6_route, DEFUN (ipv6_route_flags, ipv6_route_flags_cmd, - "ipv6 route X:X::X:X/M [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "ipv6 route X:X::X:X/M [from X:X::X:X/M] [tag (1-4294967295)] [(1-255)] [vrf NAME]", IP_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" "Emit an ICMP unreachable when matched\n" @@ -2534,16 +2565,32 @@ DEFUN (ipv6_route_flags, "One or more labels separated by '/'\n") { int idx_ipv6_prefixlen = 2; - int idx_ipv6_ifname = 3; - int idx_reject_blackhole = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv6_ifname; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[3]->text, "from")) + { + src = argv[4]->arg; + idx_ipv6_ifname = 5; + idx_reject_blackhole = 6; + idx_curr = 7; + } + else + { + src = NULL; + idx_ipv6_ifname = 3; + idx_reject_blackhole = 4; + idx_curr = 5; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 1, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6_ifname]->arg, NULL, argv[idx_reject_blackhole]->arg, @@ -2552,10 +2599,12 @@ DEFUN (ipv6_route_flags, DEFUN (ipv6_route_ifname, ipv6_route_ifname_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "ipv6 route X:X::X:X/M [from X:X::X:X/M] X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", IP_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" @@ -2569,13 +2618,29 @@ DEFUN (ipv6_route_ifname, int idx_ipv6 = 3; int idx_interface = 4; int idx_curr = 5; - char *tag, *distance, *vrf; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[3]->text, "from")) + { + src = argv[4]->arg; + idx_ipv6 = 5; + idx_interface = 6; + idx_curr = 7; + } + else + { + src = NULL; + idx_ipv6 = 3; + idx_interface = 4; + idx_curr = 5; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 1, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6]->arg, argv[idx_interface]->arg, NULL, @@ -2584,10 +2649,12 @@ DEFUN (ipv6_route_ifname, DEFUN (ipv6_route_ifname_flags, ipv6_route_ifname_flags_cmd, - "ipv6 route X:X::X:X/M X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "ipv6 route X:X::X:X/M [from X:X::X:X/M] X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", IP_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" "Emit an ICMP unreachable when matched\n" @@ -2600,17 +2667,35 @@ DEFUN (ipv6_route_ifname_flags, "One or more labels separated by '/'\n") { int idx_ipv6_prefixlen = 2; - int idx_ipv6 = 3; - int idx_interface = 4; - int idx_reject_blackhole = 5; - int idx_curr = 6; - char *tag, *distance, *vrf; + int idx_ipv6; + int idx_interface; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[3]->text, "from")) + { + src = argv[4]->arg; + idx_ipv6 = 5; + idx_interface = 6; + idx_reject_blackhole = 7; + idx_curr = 8; + } + else + { + src = NULL; + idx_ipv6 = 3; + idx_interface = 4; + idx_reject_blackhole = 5; + idx_curr = 6; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 1, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6]->arg, argv[idx_interface]->arg, argv[idx_reject_blackhole]->arg, @@ -2619,11 +2704,13 @@ DEFUN (ipv6_route_ifname_flags, DEFUN (no_ipv6_route, no_ipv6_route_cmd, - "no ipv6 route X:X::X:X/M [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "no ipv6 route X:X::X:X/M [from X:X::X:X/M] [tag (1-4294967295)] [(1-255)] [vrf NAME]", NO_STR IP_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" "Null interface\n" @@ -2635,15 +2722,29 @@ DEFUN (no_ipv6_route, "One or more labels separated by '/'\n") { int idx_ipv6_prefixlen = 3; - int idx_ipv6_ifname = 4; - int idx_curr = 5; - char *tag, *distance, *vrf; + int idx_ipv6_ifname; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[4]->text, "from")) + { + src = argv[5]->arg; + idx_ipv6_ifname = 6; + idx_curr = 7; + } + else + { + src = NULL; + idx_ipv6_ifname = 4; + idx_curr = 5; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 0, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6_ifname]->arg, NULL, NULL, tag, distance, vrf, NULL); @@ -2651,11 +2752,13 @@ DEFUN (no_ipv6_route, DEFUN (no_ipv6_route_flags, no_ipv6_route_flags_cmd, - "no ipv6 route X:X::X:X/M [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "no ipv6 route X:X::X:X/M [from X:X::X:X/M] [tag (1-4294967295)] [(1-255)] [vrf NAME]", NO_STR IP_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" "Emit an ICMP unreachable when matched\n" @@ -2668,16 +2771,32 @@ DEFUN (no_ipv6_route_flags, "One or more labels separated by '/'\n") { int idx_ipv6_prefixlen = 3; - int idx_ipv6_ifname = 4; - int idx_reject_blackhole = 5; - int idx_curr = 6; - char *tag, *distance, *vrf; + int idx_ipv6_ifname; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[4]->text, "from")) + { + src = argv[5]->arg; + idx_ipv6_ifname = 6; + idx_reject_blackhole = 7; + idx_curr = 8; + } + else + { + src = NULL; + idx_ipv6_ifname = 4; + idx_reject_blackhole = 5; + idx_curr = 6; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 0, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6_ifname]->arg, NULL, argv[idx_reject_blackhole]->arg, @@ -2686,11 +2805,13 @@ DEFUN (no_ipv6_route_flags, DEFUN (no_ipv6_route_ifname, no_ipv6_route_ifname_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "no ipv6 route X:X::X:X/M [from X:X::X:X/M] X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", NO_STR IP_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" @@ -2701,16 +2822,32 @@ DEFUN (no_ipv6_route_ifname, "One or more labels separated by '/'\n") { int idx_ipv6_prefixlen = 3; - int idx_ipv6 = 4; - int idx_interface = 5; - int idx_curr = 6; - char *tag, *distance, *vrf; + int idx_ipv6; + int idx_interface; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[4]->text, "from")) + { + src = argv[5]->arg; + idx_ipv6 = 6; + idx_interface = 7; + idx_curr = 8; + } + else + { + src = NULL; + idx_ipv6 = 4; + idx_interface = 5; + idx_curr = 6; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 0, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6]->arg, argv[idx_interface]->arg, NULL, @@ -2719,11 +2856,13 @@ DEFUN (no_ipv6_route_ifname, DEFUN (no_ipv6_route_ifname_flags, no_ipv6_route_ifname_flags_cmd, - "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", + "no ipv6 route X:X::X:X/M [from X:X::X:X/M] X:X::X:X INTERFACE [tag (1-4294967295)] [(1-255)] [vrf NAME]", NO_STR IP_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" "Emit an ICMP unreachable when matched\n" @@ -2736,17 +2875,35 @@ DEFUN (no_ipv6_route_ifname_flags, "One or more labels separated by '/'\n") { int idx_ipv6_prefixlen = 3; - int idx_ipv6 = 4; - int idx_interface = 5; - int idx_reject_blackhole = 6; - int idx_curr = 7; - char *tag, *distance, *vrf; + int idx_ipv6; + int idx_interface; + int idx_reject_blackhole; + int idx_curr; + char *src, *tag, *distance, *vrf; + + if (!strcmp(argv[4]->text, "from")) + { + src = argv[5]->arg; + idx_ipv6 = 6; + idx_interface = 7; + idx_reject_blackhole = 8; + idx_curr = 9; + } + else + { + src = NULL; + idx_ipv6 = 4; + idx_interface = 5; + idx_reject_blackhole = 6; + idx_curr = 7; + } tag = distance = vrf = NULL; zebra_vty_ip_route_tdv_helper (argc, argv, idx_curr, &tag, &distance, &vrf, NULL); return static_ipv6_func (vty, 0, argv[idx_ipv6_prefixlen]->arg, + src, argv[idx_ipv6]->arg, argv[idx_interface]->arg, argv[idx_reject_blackhole]->arg, @@ -3590,7 +3747,7 @@ static_config_ipv6 (struct vty *vty) struct route_node *rn; struct static_route *si; int write = 0; - char buf[PREFIX_STRLEN]; + char buf[SRCDEST2STR_BUFFER]; struct route_table *stable; struct vrf *vrf; struct zebra_vrf *zvrf; @@ -3602,10 +3759,10 @@ static_config_ipv6 (struct vty *vty) if ((stable = zvrf->stable[AFI_IP6][SAFI_UNICAST]) == NULL) continue; - for (rn = route_top (stable); rn; rn = route_next (rn)) + for (rn = route_top (stable); rn; rn = srcdest_route_next (rn)) for (si = rn->info; si; si = si->next) { - vty_out (vty, "ipv6 route %s", prefix2str (&rn->p, buf, sizeof buf)); + vty_out (vty, "ipv6 route %s", srcdest_rnode2str (rn, buf, sizeof buf)); switch (si->type) { -- 2.39.5