diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 02:46:33 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 02:46:33 +0200 |
commit | 0d9551dc3c53f2d46e3c0e3ecb4e4b0eb327179e (patch) | |
tree | f8bf3ba86e81b823af3fcb6fcf1f4fbe77c0b167 | |
parent | bgpd-fix-nexthop-show.patch (diff) | |
download | frr-0d9551dc3c53f2d46e3c0e3ecb4e4b0eb327179e.tar.xz frr-0d9551dc3c53f2d46e3c0e3ecb4e4b0eb327179e.zip |
Add support for route tags
Credit
------
A huge amount of credit for this patch goes to Piotr Chytla for
their 'route tags support' patch that was submitted to quagga-dev
in June 2007.
Documentation
-------------
All ipv4 and ipv6 static route commands now have a "tag" option
which allows the user to set a tag between 1 and 65535.
quagga(config)# ip route 1.1.1.1/32 10.1.1.1 tag ?
<1-65535> Tag value
quagga(config)# ip route 1.1.1.1/32 10.1.1.1 tag 40
quagga(config)#
quagga# show ip route 1.1.1.1/32
Routing entry for 1.1.1.1/32
Known via "static", distance 1, metric 0, tag 40, best
* 10.1.1.1, via swp1
quagga#
The route-map parser supports matching on tags and setting tags
!
route-map MATCH_TAG_18 permit 10
match tag 18
!
!
route-map SET_TAG_22 permit 10
set tag 22
!
BGP and OSPF support:
- matching on tags when redistribing routes from the RIB into BGP/OSPF.
- setting tags when redistribing routes from the RIB into BGP/OSPF.
BGP also supports setting a tag via a table-map, when installing BGP
routes into the RIB.
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
-rw-r--r-- | bgpd/bgp_attr.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_attr.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 8 | ||||
-rw-r--r-- | bgpd/bgp_route.h | 2 | ||||
-rw-r--r-- | bgpd/bgp_routemap.c | 211 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 94 | ||||
-rw-r--r-- | lib/zclient.c | 6 | ||||
-rw-r--r-- | lib/zclient.h | 5 | ||||
-rw-r--r-- | ospfd/ospf_asbr.c | 5 | ||||
-rw-r--r-- | ospfd/ospf_asbr.h | 3 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 6 | ||||
-rw-r--r-- | ospfd/ospf_routemap.c | 192 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 23 | ||||
-rw-r--r-- | ospfd/ospfd.c | 1 | ||||
-rw-r--r-- | ospfd/ospfd.h | 3 | ||||
-rw-r--r-- | ripd/rip_routemap.c | 23 | ||||
-rw-r--r-- | ripngd/ripng_routemap.c | 8 | ||||
-rw-r--r-- | zebra/rib.h | 20 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 42 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 885 | ||||
-rw-r--r-- | zebra/zserv.c | 34 |
21 files changed, 1474 insertions, 103 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e7a6a9e17..7709ff4a4 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -435,6 +435,7 @@ attrhash_key_make (void *p) MIX(extra->weight); MIX(extra->mp_nexthop_global_in.s_addr); MIX(extra->originator_id.s_addr); + MIX(extra->tag); } if (attr->aspath) @@ -482,6 +483,7 @@ attrhash_cmp (const void *p1, const void *p2) && ae1->aggregator_as == ae2->aggregator_as && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr && ae1->weight == ae2->weight + && ae1->tag == ae2->tag #ifdef HAVE_IPV6 && ae1->mp_nexthop_len == ae2->mp_nexthop_len && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global) @@ -618,6 +620,7 @@ bgp_attr_default_set (struct attr *attr, u_char origin) attr->aspath = aspath_empty (); attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT; + attr->extra->tag = 0; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); #ifdef HAVE_IPV6 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN; diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 5aa0c39f9..91626f25c 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -85,6 +85,9 @@ struct attr_extra /* MP Nexthop length */ u_char mp_nexthop_len; + + /* route tag */ + u_short tag; }; /* BGP core attribute structure. */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index be6cb3b25..d45ffd0e1 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5593,7 +5593,7 @@ ALIAS (no_ipv6_aggregate_address_summary_only, void bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, const struct in6_addr *nexthop6, unsigned int ifindex, - u_int32_t metric, u_char type) + u_int32_t metric, u_char type, u_short tag) { struct bgp *bgp; struct listnode *node, *nnode; @@ -5623,6 +5623,7 @@ bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop, attr.med = metric; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + attr.extra->tag = tag; for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) { @@ -6288,7 +6289,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, } #endif /* HAVE_IPV6 */ - /* Line 3 display Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */ + /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, Int/Ext/Local, Atomic, best */ vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) @@ -6301,6 +6302,9 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (attr->extra && attr->extra->weight != 0) vty_out (vty, ", weight %u", attr->extra->weight); + + if (attr->extra && attr->extra->tag != 0) + vty_out (vty, ", tag %d", attr->extra->tag); if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY)) vty_out (vty, ", valid"); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 905295b94..eab51bb62 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -217,7 +217,7 @@ extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int); extern void bgp_redistribute_add (struct prefix *, const struct in_addr *, const struct in6_addr *, unsigned int ifindex, - u_int32_t, u_char); + u_int32_t, u_char, u_short); extern void bgp_redistribute_delete (struct prefix *, u_char); extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 49cde8ea9..2d821cac5 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -76,7 +76,7 @@ o Cisco route-map length : (This will not be implemented by bgpd) metric : Done route-type : (This will not be implemented by bgpd) - tag : (This will not be implemented by bgpd) + tag : Done local-preference : Done set as-path prepend : Done @@ -96,7 +96,7 @@ o Cisco route-map metric : Done metric-type : Not yet origin : Done - tag : (This will not be implemented by bgpd) + tag : Done weight : Done o Local extensions @@ -1007,6 +1007,72 @@ struct route_map_rule_cmd route_match_interface_cmd = /* `set ip next-hop IP_ADDRESS' */ +/* Match function return 1 if match is success else return zero. */ +static route_map_result_t +route_match_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct bgp_info *bgp_info; + + if (type == RMAP_BGP) + { + tag = rule; + bgp_info = object; + + if (!bgp_info->attr->extra) + return RMAP_NOMATCH; + + return ((bgp_info->attr->extra->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH); + } + + return RMAP_NOMATCH; +} + + +/* Route map `match tag' match statement. `arg' is TAG value */ +static void * +route_match_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + + +/* Free route map's compiled 'match tag' value. */ +static void +route_match_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag matching. */ +struct route_map_rule_cmd route_match_tag_cmd = +{ + "tag", + route_match_tag, + route_match_tag_compile, + route_match_tag_free, +}; + + /* Set nexthop to object. ojbect must be pointer to struct attr. */ struct rmap_ip_nexthop_set { @@ -1878,6 +1944,73 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = route_set_aggregator_as_free, }; +/* Set tag to object. object must be pointer to struct bgp_info */ +static route_map_result_t +route_set_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct bgp_info *bgp_info; + struct attr_extra *ae; + + if (type == RMAP_BGP) + { + tag = rule; + bgp_info = object; + ae = bgp_attr_extra_get (bgp_info->attr); + + /* Set tag value */ + ae->tag=*tag; + + } + + return RMAP_OKAY; +} + +/* Route map `tag' compile function. Given string is converted to u_short. */ +static void * +route_set_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + +/* Free route map's tag value. */ +static void +route_set_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + + +/* Route map commands for tag set. */ +struct route_map_rule_cmd route_set_tag_cmd = +{ + "tag", + route_set_tag, + route_set_tag_compile, + route_set_tag_free, +}; + + #ifdef HAVE_IPV6 /* `match ipv6 address IP_ACCESS_LIST' */ @@ -3447,6 +3580,41 @@ ALIAS (no_match_interface, "Match first hop interface of route\n" "Interface name\n") +DEFUN (match_tag, + match_tag_cmd, + "match tag <1-65535>", + MATCH_STR + "Match tag of route\n" + "Tag value\n") +{ + return bgp_route_match_add (vty, vty->index, "tag", argv[0], + RMAP_EVENT_MATCH_ADDED); +} + +DEFUN (no_match_tag, + no_match_tag_cmd, + "no match tag", + NO_STR + MATCH_STR + "Match tag of route\n") +{ + if (argc == 0) + return bgp_route_match_delete (vty, vty->index, "tag", NULL, + RMAP_EVENT_MATCH_DELETED); + + return bgp_route_match_delete (vty, vty->index, "tag", argv[0], + RMAP_EVENT_MATCH_DELETED); +} + +ALIAS (no_match_tag, + no_match_tag_val_cmd, + "no match tag <1-65535>", + NO_STR + MATCH_STR + "Match tag of route\n" + "Tag value\n") + + DEFUN (set_ip_nexthop, set_ip_nexthop_cmd, "set ip next-hop A.B.C.D", @@ -4094,6 +4262,37 @@ ALIAS (no_set_aggregator_as, "AS number\n" "IP address of aggregator\n") +DEFUN (set_tag, + set_tag_cmd, + "set tag <1-65535>", + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") +{ + return bgp_route_set_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_set_tag, + no_set_tag_cmd, + "no set tag", + NO_STR + SET_STR + "Tag value for routing protocol\n") +{ + if (argc == 0) + bgp_route_set_delete(vty, vty->index, "tag", NULL); + + return bgp_route_set_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_set_tag, + no_set_tag_val_cmd, + "no set tag <1-65535>", + NO_STR + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") + #ifdef HAVE_IPV6 DEFUN (match_ipv6_address, @@ -4421,6 +4620,7 @@ bgp_route_map_init (void) route_map_install_match (&route_match_origin_cmd); route_map_install_match (&route_match_probability_cmd); route_map_install_match (&route_match_interface_cmd); + route_map_install_match (&route_match_tag_cmd); route_map_install_set (&route_set_ip_nexthop_cmd); route_map_install_set (&route_set_local_pref_cmd); @@ -4437,6 +4637,7 @@ bgp_route_map_init (void) route_map_install_set (&route_set_originator_id_cmd); route_map_install_set (&route_set_ecommunity_rt_cmd); route_map_install_set (&route_set_ecommunity_soo_cmd); + route_map_install_set (&route_set_tag_cmd); install_element (RMAP_NODE, &match_peer_cmd); install_element (RMAP_NODE, &match_peer_local_cmd); @@ -4488,6 +4689,9 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &match_interface_cmd); install_element (RMAP_NODE, &no_match_interface_cmd); install_element (RMAP_NODE, &no_match_interface_val_cmd); + install_element (RMAP_NODE, &match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_val_cmd); install_element (RMAP_NODE, &set_ip_nexthop_cmd); install_element (RMAP_NODE, &set_ip_nexthop_peer_cmd); @@ -4537,6 +4741,9 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &set_originator_id_cmd); install_element (RMAP_NODE, &no_set_originator_id_cmd); install_element (RMAP_NODE, &no_set_originator_id_val_cmd); + install_element (RMAP_NODE, &set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_val_cmd); #ifdef HAVE_IPV6 route_map_install_match (&route_match_ipv6_address_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 9391030c1..369bcddf0 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -402,32 +402,41 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) api.nexthop_num = stream_getc (s); nexthop.s_addr = stream_get_ipv4 (s); } + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); /* ifindex, unused */ } + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; + if (command == ZEBRA_IPV4_ROUTE_ADD) { if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u", + zlog_debug("Zebra rcvd: IPv4 route add %s %s/%d nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } bgp_redistribute_add((struct prefix *)&p, &nexthop, NULL, ifindex, - api.metric, api.type); + api.metric, api.type, api.tag); } else { @@ -435,12 +444,13 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length) { char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv4 route delete %s %s/%d " - "nexthop %s metric %u", + "nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } bgp_redistribute_delete((struct prefix *)&p, api.type); } @@ -479,20 +489,28 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) api.nexthop_num = stream_getc (s); stream_get (&nexthop, s, 16); } + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); /* ifindex, unused */ } + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; + /* Simply ignore link-local address. */ if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) return 0; @@ -502,15 +520,16 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u", + zlog_debug("Zebra rcvd: IPv6 route add %s %s/%d nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } bgp_redistribute_add ((struct prefix *)&p, NULL, &nexthop, ifindex, - api.metric, api.type); + api.metric, api.type, api.tag); } else { @@ -518,12 +537,13 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra rcvd: IPv6 route delete %s %s/%d " - "nexthop %s metric %u", + "nexthop %s metric %u tag %d", zebra_route_string(api.type), inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])), p.prefixlen, inet_ntop(AF_INET6, &nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } bgp_redistribute_delete ((struct prefix *) &p, api.type); } @@ -876,6 +896,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, u_int32_t nhcount, metric; struct bgp_info local_info; struct bgp_info *info_cp = &local_info; + u_short tag; if (zclient->sock < 0) return; @@ -889,6 +910,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, flags = 0; peer = info->peer; + if ((info->attr->extra) && (info->attr->extra->tag != 0)) + tag = info->attr->extra->tag; + else + tag = 0; + if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) { SET_FLAG (flags, ZEBRA_FLAG_IBGP); @@ -937,6 +963,9 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, { metric = info_cp->attr->med; nexthop = &info_cp->attr->nexthop; + + if (info_cp->attr->extra) + tag = info_cp->attr->extra->tag; } BGP_INFO_ATTR_BUF_FREE(info_cp); } @@ -988,6 +1017,12 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; + if (tag) + { + SET_FLAG (api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } + distance = bgp_distance_apply (p, info, bgp); if (distance) @@ -999,10 +1034,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (BGP_DEBUG(zebra, ZEBRA)) { int i; - zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u" + zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u tag %d" " count %d", (valid_nh_count ? "add":"delete"), inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric, api.nexthop_num); + p->prefixlen, api.metric, api.tag, api.nexthop_num); for (i = 0; i < api.nexthop_num; i++) zlog_debug(" IPv4 [nexthop %d] %s", i+1, inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1]))); @@ -1069,6 +1104,9 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, { metric = info_cp->attr->med; nexthop = bgp_info_to_ipv6_nexthop(info_cp); + + if (info_cp->attr->extra) + tag = info_cp->attr->extra->tag; } BGP_INFO_ATTR_BUF_FREE(info_cp); } @@ -1149,13 +1187,19 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = metric; + if (tag) + { + SET_FLAG (api.message, ZAPI_MESSAGE_TAG); + api.tag = tag; + } + if (BGP_DEBUG(zebra, ZEBRA)) { int i; - zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u", + zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u tag %d", valid_nh_count ? "add" : "delete", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), - p->prefixlen, api.metric); + p->prefixlen, api.metric, api.tag); for (i = 0; i < api.nexthop_num; i++) zlog_debug(" IPv6 [nexthop %d] %s", i+1, inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1]))); @@ -1233,14 +1277,21 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; + if ((info->attr->extra) && (info->attr->extra->tag != 0)) + { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->extra->tag; + } + if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u", + zlog_debug("Zebra send: IPv4 route delete %s/%d nexthop %s metric %u tag %d", inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, @@ -1291,14 +1342,21 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi) SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; + if ((info->attr->extra) && (info->attr->extra->tag != 0)) + { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = info->attr->extra->tag; + } + if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; - zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u", + zlog_debug("Zebra send: IPv6 route delete %s/%d nexthop %s metric %u tag %d", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])), - api.metric); + api.metric, + api.tag); } zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, diff --git a/lib/zclient.c b/lib/zclient.c index 8b4597714..72367206b 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -456,6 +456,8 @@ zclient_connect (struct thread *t) * If ZAPI_MESSAGE_METRIC is set, the metric value is written as an 8 * byte value. * + * If ZAPI_MESSAGE_TAG is set, the tag value is written as a 2 byte value + * * XXX: No attention paid to alignment. */ int @@ -512,6 +514,8 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, stream_putc (s, api->distance); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) stream_putl (s, api->metric); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) + stream_putw (s, api->tag); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); @@ -566,6 +570,8 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, stream_putc (s, api->distance); if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) stream_putl (s, api->metric); + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_TAG)) + stream_putw (s, api->tag); /* Put length at the first point of the stream. */ stream_putw_at (s, 0, stream_get_endp (s)); diff --git a/lib/zclient.h b/lib/zclient.h index 5c24ee459..9b627b65f 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -92,6 +92,7 @@ struct zclient #define ZAPI_MESSAGE_IFINDEX 0x02 #define ZAPI_MESSAGE_DISTANCE 0x04 #define ZAPI_MESSAGE_METRIC 0x08 +#define ZAPI_MESSAGE_TAG 0x20 /* Zserv protocol message header */ struct zserv_header @@ -125,6 +126,8 @@ struct zapi_ipv4 u_char distance; u_int32_t metric; + + u_short tag; }; /* Prototypes of zebra client service functions. */ @@ -185,6 +188,8 @@ struct zapi_ipv6 u_char distance; u_int32_t metric; + + u_short tag; }; extern int zapi_ipv6_route (u_char cmd, struct zclient *zclient, diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index dbf7f11f5..f4140b858 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -135,7 +135,8 @@ ospf_route_map_set_compare (struct route_map_set_values *values1, /* Add an External info for AS-external-LSA. */ struct external_info * ospf_external_info_add (u_char type, struct prefix_ipv4 p, - unsigned int ifindex, struct in_addr nexthop) + unsigned int ifindex, struct in_addr nexthop, + u_short tag) { struct external_info *new; struct route_node *rn; @@ -162,7 +163,7 @@ ospf_external_info_add (u_char type, struct prefix_ipv4 p, new->p = p; new->ifindex = ifindex; new->nexthop = nexthop; - new->tag = 0; + new->tag = tag; if (rn) rn->info = new; diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index 724acf481..bb773c979 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -62,7 +62,8 @@ extern int ospf_route_map_set_compare (struct route_map_set_values *, extern struct external_info *ospf_external_info_add (u_char, struct prefix_ipv4, unsigned int, - struct in_addr); + struct in_addr, + u_short); extern void ospf_external_info_delete (u_char, struct prefix_ipv4); extern struct external_info *ospf_external_info_lookup (u_char, struct prefix_ipv4 *); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 31cbaaef2..eabfa7b68 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -1638,8 +1638,8 @@ ospf_external_lsa_body_set (struct stream *s, struct external_info *ei, /* Put forwarding address. */ stream_put_ipv4 (s, fwd_addr.s_addr); - /* Put route tag -- This value should be introduced from configuration. */ - stream_putl (s, 0); + /* Put route tag -- only first 16bits are used for compatibility */ + stream_putl (s, ei->tag); } /* Create new external-LSA. */ @@ -2152,7 +2152,7 @@ ospf_default_originate_timer (struct thread *thread) /* If there is no default route via redistribute, then originate AS-external-LSA with nexthop 0 (self). */ nexthop.s_addr = 0; - ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop); + ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop, 0); } if ((ei = ospf_default_external_info (ospf))) diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index d0ebce66e..7bd6c3d96 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -417,6 +417,67 @@ struct route_map_rule_cmd route_match_interface_cmd = route_match_interface_free }; +/* Match function return 1 if match is success else return zero. */ +static route_map_result_t +route_match_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct external_info *ei; + + if (type == RMAP_OSPF) + { + tag = rule; + ei = object; + + return ((ei->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH); + } + + return RMAP_NOMATCH; +} + +/* Route map `match tag' match statement. `arg' is TAG value */ +static void * +route_match_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + +/* Free route map's compiled 'match tag' value. */ +static void +route_match_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag matching. */ +struct route_map_rule_cmd route_match_tag_cmd = +{ + "tag", + route_match_tag, + route_match_tag_compile, + route_match_tag_free, +}; + + /* `set metric METRIC' */ /* Set metric to attribute. */ static route_map_result_t @@ -531,6 +592,67 @@ struct route_map_rule_cmd route_set_metric_type_cmd = route_set_metric_type_free, }; +static route_map_result_t +route_set_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct external_info *ei; + + if (type == RMAP_OSPF) + { + tag = rule; + ei = object; + + /* Set tag value */ + ei->tag=*tag; + } + + return RMAP_OKAY; +} + +/* Route map `tag' compile function. Given string is converted to u_short. */ +static void * +route_set_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + +/* Free route map's tag value. */ +static void +route_set_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag set. */ +struct route_map_rule_cmd route_set_tag_cmd = +{ + "tag", + route_set_tag, + route_set_tag_compile, + route_set_tag_free, +}; + DEFUN (match_ip_nexthop, match_ip_nexthop_cmd, "match ip next-hop (<1-199>|<1300-2699>|WORD)", @@ -716,6 +838,37 @@ ALIAS (no_match_interface, "Match first hop interface of route\n" "Interface name\n") +DEFUN (match_tag, + match_tag_cmd, + "match tag <1-65535>", + MATCH_STR + "Match tag of route\n" + "Tag value\n") +{ + return ospf_route_match_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_match_tag, + no_match_tag_cmd, + "no match tag", + NO_STR + MATCH_STR + "Match tag of route\n") +{ + if (argc == 0) + return ospf_route_match_delete (vty, vty->index, "tag", NULL); + + return ospf_route_match_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_match_tag, + no_match_tag_val_cmd, + "no match tag <1-65535>", + NO_STR + MATCH_STR + "Match tag of route\n" + "Tag value\n") + DEFUN (set_metric, set_metric_cmd, "set metric <0-4294967295>", @@ -785,6 +938,37 @@ ALIAS (no_set_metric_type, "OSPF[6] external type 1 metric\n" "OSPF[6] external type 2 metric\n") +DEFUN (set_tag, + set_tag_cmd, + "set tag <1-65535>", + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") +{ + return ospf_route_set_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_set_tag, + no_set_tag_cmd, + "no set tag", + NO_STR + SET_STR + "Tag value for routing protocol\n") +{ + if (argc == 0) + ospf_route_set_delete(vty, vty->index, "tag", NULL); + + return ospf_route_set_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_set_tag, + no_set_tag_val_cmd, + "no set tag <1-65535>", + NO_STR + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") + /* Route-map init */ void ospf_route_map_init (void) @@ -801,9 +985,11 @@ ospf_route_map_init (void) route_map_install_match (&route_match_ip_address_cmd); route_map_install_match (&route_match_ip_address_prefix_list_cmd); route_map_install_match (&route_match_interface_cmd); + route_map_install_match (&route_match_tag_cmd); route_map_install_set (&route_set_metric_cmd); route_map_install_set (&route_set_metric_type_cmd); + route_map_install_set (&route_set_tag_cmd); install_element (RMAP_NODE, &match_ip_nexthop_cmd); install_element (RMAP_NODE, &no_match_ip_nexthop_cmd); @@ -820,6 +1006,9 @@ ospf_route_map_init (void) install_element (RMAP_NODE, &match_interface_cmd); install_element (RMAP_NODE, &no_match_interface_cmd); install_element (RMAP_NODE, &no_match_interface_val_cmd); + install_element (RMAP_NODE, &match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_val_cmd); install_element (RMAP_NODE, &set_metric_cmd); install_element (RMAP_NODE, &no_set_metric_cmd); @@ -827,4 +1016,7 @@ ospf_route_map_init (void) install_element (RMAP_NODE, &set_metric_type_cmd); install_element (RMAP_NODE, &no_set_metric_type_cmd); install_element (RMAP_NODE, &no_set_metric_type_val_cmd); + install_element (RMAP_NODE, &set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_val_cmd); } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index b6d3260b4..94edc2863 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -349,6 +349,12 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) if (distance) SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); + /* Check if path type is ASE and use only 16bit tags */ + if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) || + (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) && + (or->u.ext.tag > 0) && (or->u.ext.tag < UINT16_MAX)) + SET_FLAG (message, ZAPI_MESSAGE_TAG); + /* Make packet. */ s = zclient->obuf; stream_reset (s); @@ -416,6 +422,9 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) stream_putl (s, or->cost); } + if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) + stream_putw (s, (u_short)or->u.ext.tag); + stream_putw_at (s, 0, stream_get_endp (s)); zclient_send_message(zclient); @@ -523,6 +532,7 @@ ospf_zebra_add_discard (struct prefix_ipv4 *p) SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; + api.tag = 0; zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); @@ -546,6 +556,7 @@ ospf_zebra_delete_discard (struct prefix_ipv4 *p) SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; + api.tag = 0; zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); @@ -860,6 +871,10 @@ ospf_zebra_read_ipv4 (int command, struct zclient *zclient, api.distance = stream_getc (s); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; ospf = ospf_lookup (); if (ospf == NULL) @@ -877,8 +892,12 @@ ospf_zebra_read_ipv4 (int command, struct zclient *zclient, * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT)) * return 0; */ - - ei = ospf_external_info_add (api.type, p, ifindex, nexthop); + + /* Protocol tag overwrites all other tag value send by zebra */ + if (ospf->dtag[api.type] > 0) + api.tag = ospf->dtag[api.type]; + + ei = ospf_external_info_add (api.type, p, ifindex, nexthop, api.tag); if (ospf->router_id.s_addr == 0) /* Set flags to generate AS-external-LSA originate event diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 4cddca67d..272c544bc 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -189,6 +189,7 @@ ospf_new (void) { new->dmetric[i].type = -1; new->dmetric[i].value = -1; + new->dtag[i] = 0; } new->default_metric = -1; new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 9920a6e2e..11525a5fb 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -244,6 +244,9 @@ struct ospf -1 means metric value is not set. */ } dmetric [ZEBRA_ROUTE_MAX + 1]; + /* Redistribute tag info. */ + u_short dtag [ZEBRA_ROUTE_MAX + 1]; + /* For redistribute route map. */ struct { diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 9bafdcde1..cc0ed61ff 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -485,9 +485,22 @@ static void * route_match_tag_compile (const char *arg) { u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + if (tmp < 1) + return NULL; tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); - *tag = atoi (arg); + + if (!tag) + return tag; + + *tag = tmp; return tag; } @@ -937,7 +950,7 @@ ALIAS (no_match_ip_address_prefix_list, DEFUN (match_tag, match_tag_cmd, - "match tag <0-65535>", + "match tag <1-65535>", MATCH_STR "Match tag of route\n" "Metric value\n") @@ -960,7 +973,7 @@ DEFUN (no_match_tag, ALIAS (no_match_tag, no_match_tag_val_cmd, - "no match tag <0-65535>", + "no match tag <1-65535>", NO_STR MATCH_STR "Match tag of route\n" @@ -1060,7 +1073,7 @@ ALIAS (no_set_ip_nexthop, DEFUN (set_tag, set_tag_cmd, - "set tag <0-65535>", + "set tag <1-65535>", SET_STR "Tag value for routing protocol\n" "Tag value\n") @@ -1083,7 +1096,7 @@ DEFUN (no_set_tag, ALIAS (no_set_tag, no_set_tag_val_cmd, - "no set tag <0-65535>", + "no set tag <1-65535>", NO_STR SET_STR "Tag value for routing protocol\n" diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index f4fadb67e..a316301ab 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -564,7 +564,7 @@ ALIAS (no_match_interface, DEFUN (match_tag, match_tag_cmd, - "match tag <0-65535>", + "match tag <1-65535>", MATCH_STR "Match tag of route\n" "Metric value\n") @@ -587,7 +587,7 @@ DEFUN (no_match_tag, ALIAS (no_match_tag, no_match_tag_val_cmd, - "no match tag <0-65535>", + "no match tag <1-65535>", NO_STR MATCH_STR "Match tag of route\n" @@ -675,7 +675,7 @@ ALIAS (no_set_ipv6_nexthop_local, DEFUN (set_tag, set_tag_cmd, - "set tag <0-65535>", + "set tag <1-65535>", SET_STR "Tag value for routing protocol\n" "Tag value\n") @@ -698,7 +698,7 @@ DEFUN (no_set_tag, ALIAS (no_set_tag, no_set_tag_val_cmd, - "no set tag <0-65535>", + "no set tag <1-65535>", NO_STR SET_STR "Tag value for routing protocol\n" diff --git a/zebra/rib.h b/zebra/rib.h index 833b892cb..c2b28d196 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -57,6 +57,9 @@ struct rib /* Distance. */ u_char distance; + /* Tag */ + u_short tag; + /* Flags of this route. * This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed * to clients via Zserv @@ -165,6 +168,9 @@ struct static_ipv4 /* Administrative distance. */ u_char distance; + /* Tag */ + u_short tag; + /* Flag for this static route's type. */ u_char type; #define STATIC_IPV4_GATEWAY 1 @@ -197,6 +203,9 @@ struct static_ipv6 /* Administrative distance. */ u_char distance; + /* Tag */ + u_short tag; + /* Flag for this static route's type. */ u_char type; #define STATIC_IPV6_GATEWAY 1 @@ -393,11 +402,11 @@ extern unsigned long rib_score_proto (u_char proto); extern int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_char distance, u_int32_t vrf_id); + u_char flags, u_short tag, u_char distance, u_int32_t vrf_id); extern int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char distance, u_int32_t vrf_id); + u_short tag, u_char distance, u_int32_t vrf_id); #ifdef HAVE_IPV6 extern int @@ -417,8 +426,8 @@ extern struct route_table *rib_table_ipv6; extern int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - const char *ifname, u_char flags, u_char distance, - u_int32_t vrf_id); + const char *ifname, u_char flags, u_short tag, + u_char distance, u_int32_t vrf_id); extern int rib_add_ipv6_multipath (struct prefix_ipv6 *, struct rib *, safi_t, @@ -426,7 +435,8 @@ rib_add_ipv6_multipath (struct prefix_ipv6 *, struct rib *, safi_t, extern int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - const char *ifname, u_char distance, u_int32_t vrf_id); + const char *ifname, u_short tag, u_char distance, + u_int32_t vrf_id); #endif /* HAVE_IPV6 */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index af04adaa4..7caa793f2 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2303,6 +2303,10 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) if (rib) { + /* if tag value changed , update old value in RIB */ + if (rib->tag != si->tag) + rib->tag = si->tag; + /* Same distance static route is there. Update it with new nexthop. */ route_unlock_node (rn); @@ -2330,6 +2334,7 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) rib->metric = 0; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; + rib->tag = si->tag; switch (si->type) { @@ -2393,7 +2398,8 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) continue; - if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) + if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance && + rib->tag == si->tag) break; } @@ -2433,7 +2439,7 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) /* Add static route into static route configuration. */ int static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char flags, u_char distance, u_int32_t vrf_id) + u_char flags, u_short tag, u_char distance, u_int32_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -2466,7 +2472,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4)) && (! ifname || strcmp (ifname, si->gate.ifname) == 0)) { - if (distance == si->distance) + if ((distance == si->distance) && (tag == si->tag)) { route_unlock_node (rn); return 0; @@ -2476,9 +2482,9 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, } } - /* Distance changed. */ + /* Distance or tag changed. */ if (update) - static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id); + static_delete_ipv4 (p, gate, ifname, update->tag, update->distance, vrf_id); /* Make new static route structure. */ si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4)); @@ -2486,6 +2492,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, si->type = type; si->distance = distance; si->flags = flags; + si->tag = tag; if (gate) si->gate.ipv4 = *gate; @@ -2528,7 +2535,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, /* Delete static route from static route configuration. */ int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, - u_char distance, u_int32_t vrf_id) + u_short tag, u_char distance, u_int32_t vrf_id) { u_char type = 0; struct route_node *rn; @@ -2557,7 +2564,8 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, for (si = rn->info; si; si = si->next) if (type == si->type && (! gate || IPV4_ADDR_SAME (gate, &si->gate.ipv4)) - && (! ifname || strcmp (ifname, si->gate.ifname) == 0)) + && (! ifname || strcmp (ifname, si->gate.ifname) == 0) + && (! tag || (tag == si->tag))) break; /* Can't find static route. */ @@ -2972,6 +2980,10 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) if (rib) { + /* if tag value changed , update old value in RIB */ + if (rib->tag != si->tag) + rib->tag = si->tag; + /* Same distance static route is there. Update it with new nexthop. */ route_unlock_node (rn); @@ -3000,6 +3012,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si) rib->metric = 0; rib->table = zebrad.rtm_table_default; rib->nexthop_num = 0; + rib->tag = si->tag; switch (si->type) { @@ -3064,7 +3077,8 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) continue; - if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance) + if (rib->type == ZEBRA_ROUTE_STATIC && rib->distance == si->distance && + rib->tag == si->tag) break; } @@ -3106,8 +3120,8 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si) /* Add static route into static route configuration. */ int static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - const char *ifname, u_char flags, u_char distance, - u_int32_t vrf_id) + const char *ifname, u_char flags, u_short tag, + u_char distance, u_int32_t vrf_id) { struct route_node *rn; struct static_ipv6 *si; @@ -3136,6 +3150,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, { if (distance == si->distance && type == si->type + && tag == si->tag && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6)) && (! ifname || strcmp (ifname, si->ifname) == 0)) { @@ -3150,6 +3165,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, si->type = type; si->distance = distance; si->flags = flags; + si->tag = tag; switch (type) { @@ -3194,7 +3210,8 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, /* Delete static route from static route configuration. */ int static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, - const char *ifname, u_char distance, u_int32_t vrf_id) + const char *ifname, u_short tag, u_char distance, + u_int32_t vrf_id) { struct route_node *rn; struct static_ipv6 *si; @@ -3215,7 +3232,8 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, if (distance == si->distance && type == si->type && (! gate || IPV6_ADDR_SAME (gate, &si->ipv6)) - && (! ifname || strcmp (ifname, si->ifname) == 0)) + && (! ifname || strcmp (ifname, si->ifname) == 0) + && (! tag || (tag == si->tag))) break; /* Can't find static route. */ diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index c8e0d1f6f..6031da876 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -36,7 +36,8 @@ static int zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, const char *mask_str, const char *gate_str, - const char *flag_str, const char *distance_str) + const char *flag_str, const char *tag_str, + const char *distance_str) { int ret; u_char distance; @@ -45,6 +46,7 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, struct in_addr mask; const char *ifname; u_char flag = 0; + u_short tag = 0; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -74,6 +76,10 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, else distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + /* tag */ + if (tag_str) + tag = atoi(tag_str); + /* Null0 static route. */ if ((gate_str != NULL) && (strncasecmp (gate_str, "Null0", strlen (gate_str)) == 0)) { @@ -83,9 +89,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, return CMD_WARNING; } if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, distance, 0); + static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, tag, distance, 0); else - static_delete_ipv4 (&p, NULL, NULL, distance, 0); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, 0); return CMD_SUCCESS; } @@ -109,9 +115,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, if (gate_str == NULL) { if (add_cmd) - static_add_ipv4 (&p, NULL, NULL, flag, distance, 0); + static_add_ipv4 (&p, NULL, NULL, flag, tag, distance, 0); else - static_delete_ipv4 (&p, NULL, NULL, distance, 0); + static_delete_ipv4 (&p, NULL, NULL, tag, distance, 0); return CMD_SUCCESS; } @@ -125,9 +131,9 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, ifname = gate_str; if (add_cmd) - static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0); + static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, tag, distance, 0); else - static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0); + static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, tag, distance, 0); return CMD_SUCCESS; } @@ -143,7 +149,22 @@ DEFUN (ip_route, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, NULL); +} + +DEFUN (ip_route_tag, + ip_route_tag_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n") +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], NULL); } DEFUN (ip_route_flags, @@ -157,7 +178,24 @@ DEFUN (ip_route_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, NULL); +} + +DEFUN (ip_route_flags_tag, + ip_route_flags_tag_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") + +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], NULL); } DEFUN (ip_route_flags2, @@ -169,7 +207,22 @@ DEFUN (ip_route_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, NULL); +} + +DEFUN (ip_route_flags2_tag, + ip_route_flags2_tag_cmd, + "ip route A.B.C.D/M (reject|blackhole) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") + +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], NULL); } /* Mask as A.B.C.D format. */ @@ -184,7 +237,24 @@ DEFUN (ip_route_mask, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL); +} + +DEFUN (ip_route_mask_tag, + ip_route_mask_tag_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n") + +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL); } DEFUN (ip_route_mask_flags, @@ -199,7 +269,25 @@ DEFUN (ip_route_mask_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL); +} + +DEFUN (ip_route_mask_flags_tag, + ip_route_mask_flags_tag_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") + +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL); } DEFUN (ip_route_mask_flags2, @@ -212,7 +300,22 @@ DEFUN (ip_route_mask_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL); +} + +DEFUN (ip_route_mask_flags2_tag, + ip_route_mask_flags2_tag_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535>", + IP_STR + "Establish static routes\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") +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL); } /* Distance option value. */ @@ -227,7 +330,24 @@ DEFUN (ip_route_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, argv[2]); +} + +DEFUN (ip_route_tag_distance, + ip_route_tag_distance_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n") + +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], argv[3]); } DEFUN (ip_route_flags_distance, @@ -242,7 +362,24 @@ DEFUN (ip_route_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, argv[3]); +} + +DEFUN (ip_route_flags_tag_distance, + ip_route_flags_tag_distance_cmd, + "ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\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") +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], argv[4]); } DEFUN (ip_route_flags_distance2, @@ -255,7 +392,22 @@ DEFUN (ip_route_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2]); + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, argv[2]); +} + +DEFUN (ip_route_flags_tag_distance2, + ip_route_flags_tag_distance2_cmd, + "ip route A.B.C.D/M (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\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") +{ + return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], argv[3]); } DEFUN (ip_route_mask_distance, @@ -270,9 +422,45 @@ DEFUN (ip_route_mask_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); } +DEFUN (ip_route_mask_tag_distance, + ip_route_mask_tag_distance_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n") +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); +} + +DEFUN (ip_route_mask_flags_tag_distance, + ip_route_mask_flags_tag_distance_cmd, + "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\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" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n") +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + + DEFUN (ip_route_mask_flags_distance, ip_route_mask_flags_distance_cmd, "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) <1-255>", @@ -286,7 +474,7 @@ DEFUN (ip_route_mask_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); } DEFUN (ip_route_mask_flags_distance2, @@ -300,7 +488,23 @@ DEFUN (ip_route_mask_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]); + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); +} + +DEFUN (ip_route_mask_flags_tag_distance2, + ip_route_mask_flags_tag_distance2_cmd, + "ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Set tag for this route\n" + "Tag value\n" + "Distance value for this route\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n") +{ + return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); } DEFUN (no_ip_route, @@ -314,7 +518,23 @@ DEFUN (no_ip_route, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, NULL); +} + +DEFUN (no_ip_route_tag, + no_ip_route_tag_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], NULL); } ALIAS (no_ip_route, @@ -329,6 +549,20 @@ ALIAS (no_ip_route, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") +ALIAS (no_ip_route_tag, + no_ip_route_flags_tag_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n") + DEFUN (no_ip_route_flags2, no_ip_route_flags2_cmd, "no ip route A.B.C.D/M (reject|blackhole)", @@ -339,7 +573,22 @@ DEFUN (no_ip_route_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, NULL); +} + +DEFUN (no_ip_route_flags2_tag, + no_ip_route_flags2_tag_cmd, + "no ip route A.B.C.D/M (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, argv[1], NULL); } DEFUN (no_ip_route_mask, @@ -354,7 +603,24 @@ DEFUN (no_ip_route_mask, "IP gateway interface name\n" "Null interface\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL); +} + +DEFUN (no_ip_route_mask_tag, + no_ip_route_mask_tag_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL); } ALIAS (no_ip_route_mask, @@ -370,6 +636,21 @@ ALIAS (no_ip_route_mask, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") +ALIAS (no_ip_route_mask_tag, + no_ip_route_mask_flags_tag_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n") + DEFUN (no_ip_route_mask_flags2, no_ip_route_mask_flags2_cmd, "no ip route A.B.C.D A.B.C.D (reject|blackhole)", @@ -381,9 +662,26 @@ DEFUN (no_ip_route_mask_flags2, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL); +} + +DEFUN (no_ip_route_mask_flags2_tag, + no_ip_route_mask_flags2_tag_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL); } + DEFUN (no_ip_route_distance, no_ip_route_distance_cmd, "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) <1-255>", @@ -396,7 +694,24 @@ DEFUN (no_ip_route_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, argv[2]); +} + +DEFUN (no_ip_route_tag_distance, + no_ip_route_tag_distance_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], argv[3]); } DEFUN (no_ip_route_flags_distance, @@ -412,7 +727,25 @@ DEFUN (no_ip_route_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], NULL, argv[3]); +} + +DEFUN (no_ip_route_flags_tag_distance, + no_ip_route_flags_tag_distance_cmd, + "no ip route A.B.C.D/M (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], argv[4]); } DEFUN (no_ip_route_flags_distance2, @@ -426,7 +759,23 @@ DEFUN (no_ip_route_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2]); + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], NULL, argv[2]); +} + +DEFUN (no_ip_route_flags_tag_distance2, + no_ip_route_flags_tag_distance2_cmd, + "no ip route A.B.C.D/M (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix (e.g. 10.0.0.0/8)\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2] , argv[3]); } DEFUN (no_ip_route_mask_distance, @@ -442,7 +791,25 @@ DEFUN (no_ip_route_mask_distance, "Null interface\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); +} + +DEFUN (no_ip_route_mask_tag_distance, + no_ip_route_mask_tag_distance_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE|null0) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Null interface\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); } DEFUN (no_ip_route_mask_flags_distance, @@ -459,7 +826,26 @@ DEFUN (no_ip_route_mask_flags_distance, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); +} + +DEFUN (no_ip_route_mask_flags_tag_distance, + no_ip_route_mask_flags_tag_distance_cmd, + "no ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "IP gateway address\n" + "IP gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } DEFUN (no_ip_route_mask_flags_distance2, @@ -474,7 +860,24 @@ DEFUN (no_ip_route_mask_flags_distance2, "Silently discard pkts when matched\n" "Distance value for this route\n") { - return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]); + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); +} + +DEFUN (no_ip_route_mask_flags_tag_distance2, + no_ip_route_mask_flags_tag_distance2_cmd, + "no ip route A.B.C.D A.B.C.D (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IP destination prefix\n" + "IP destination prefix mask\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Tag of this route\n" + "Tag value\n" + "Distance value for this route\n") +{ + return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); } /* New RIB. Detailed information for IPv4 route. */ @@ -492,6 +895,8 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) VTY_NEWLINE); vty_out (vty, " Known via \"%s\"", zebra_route_string (rib->type)); vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric); + if (rib->tag) + vty_out (vty, ", tag %d", rib->tag); if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) vty_out (vty, ", best"); if (rib->refcnt) @@ -782,6 +1187,46 @@ DEFUN (show_ipv6_nht, return CMD_SUCCESS; } +DEFUN (show_ip_route_tag, + show_ip_route_tag_cmd, + "show ip route tag <1-65535>", + SHOW_STR + IP_STR + "IP routing table\n" + "Show only routes with tag\n" + "Tag value\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + int first = 1; + u_short tag = 0; + + if (argv[0]) + tag = atoi(argv[0]); + + table = vrf_table (AFI_IP, SAFI_UNICAST, 0); + if (! table) + return CMD_SUCCESS; + + /* Show all IPv4 routes with matching tag value. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (rib->tag != tag) + continue; + + if (first) + { + vty_out (vty, SHOW_ROUTE_V4_HEADER, VTY_NEWLINE, VTY_NEWLINE, + VTY_NEWLINE); + first = 0; + } + vty_show_ip_route (vty, rn, rib); + } + return CMD_SUCCESS; +} + DEFUN (show_ip_route_prefix_longer, show_ip_route_prefix_longer_cmd, "show ip route A.B.C.D/M longer-prefixes", @@ -1207,6 +1652,9 @@ static_config_ipv4 (struct vty *vty) vty_out (vty, " %s", "blackhole"); } + if (si->tag) + vty_out (vty, " tag %d", si->tag); + if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) vty_out (vty, " %d", si->distance); @@ -1257,7 +1705,8 @@ DEFUN (show_ip_mroute, static int static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, const char *gate_str, const char *ifname, - const char *flag_str, const char *distance_str) + const char *flag_str, const char *tag_str, + const char *distance_str) { int ret; u_char distance; @@ -1267,6 +1716,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, u_char type = 0; int table = 0; u_char flag = 0; + u_short tag = 0; ret = str2prefix (dest_str, &p); if (ret <= 0) @@ -1301,6 +1751,10 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, else distance = ZEBRA_STATIC_DISTANCE_DEFAULT; + /* tag */ + if (tag_str) + tag = atoi(tag_str); + /* When gateway is valid IPv6 addrees, then gate is treated as nexthop address other case gate is treated as interface name. */ ret = inet_pton (AF_INET6, gate_str, &gate_addr); @@ -1332,9 +1786,9 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } if (add_cmd) - static_add_ipv6 (&p, type, gate, ifname, flag, distance, table); + static_add_ipv6 (&p, type, gate, ifname, flag, tag, distance, table); else - static_delete_ipv6 (&p, type, gate, ifname, distance, table); + static_delete_ipv6 (&p, type, gate, ifname, tag, distance, table); return CMD_SUCCESS; } @@ -1348,7 +1802,21 @@ DEFUN (ipv6_route, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, NULL); +} + +DEFUN (ipv6_route_tag, + ipv6_route_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], NULL); } DEFUN (ipv6_route_flags, @@ -1362,7 +1830,23 @@ DEFUN (ipv6_route_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL); +} + +DEFUN (ipv6_route_flags_tag, + ipv6_route_flags_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL); } DEFUN (ipv6_route_ifname, @@ -1374,7 +1858,20 @@ DEFUN (ipv6_route_ifname, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL); +} +DEFUN (ipv6_route_ifname_tag, + ipv6_route_ifname_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL); } DEFUN (ipv6_route_ifname_flags, @@ -1388,7 +1885,23 @@ DEFUN (ipv6_route_ifname_flags, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL); +} + +DEFUN (ipv6_route_ifname_flags_tag, + ipv6_route_ifname_flags_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL); } DEFUN (ipv6_route_pref, @@ -1401,7 +1914,22 @@ DEFUN (ipv6_route_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL, argv[2]); +} + +DEFUN (ipv6_route_pref_tag, + ipv6_route_pref_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\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") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2], argv[3]); } DEFUN (ipv6_route_flags_pref, @@ -1416,7 +1944,24 @@ DEFUN (ipv6_route_flags_pref, "Silently discard pkts when matched\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); +} + +DEFUN (ipv6_route_flags_pref_tag, + ipv6_route_flags_pref_tag_cmd, + "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\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") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); } DEFUN (ipv6_route_ifname_pref, @@ -1429,7 +1974,22 @@ DEFUN (ipv6_route_ifname_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); +} + +DEFUN (ipv6_route_ifname_pref_tag, + ipv6_route_ifname_pref_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\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") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); } DEFUN (ipv6_route_ifname_flags_pref, @@ -1444,7 +2004,24 @@ DEFUN (ipv6_route_ifname_flags_pref, "Silently discard pkts when matched\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]); + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); +} + +DEFUN (ipv6_route_ifname_flags_pref_tag, + ipv6_route_ifname_flags_pref_tag_cmd, + "ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>", + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\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") +{ + return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } DEFUN (no_ipv6_route, @@ -1457,7 +2034,22 @@ DEFUN (no_ipv6_route, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL); +} + +DEFUN (no_ipv6_route_tag, + no_ipv6_route_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], NULL); } ALIAS (no_ipv6_route, @@ -1472,6 +2064,20 @@ ALIAS (no_ipv6_route, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") +ALIAS (no_ipv6_route_tag, + no_ipv6_route_flags_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") + DEFUN (no_ipv6_route_ifname, no_ipv6_route_ifname_cmd, "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE", @@ -1482,7 +2088,22 @@ DEFUN (no_ipv6_route_ifname, "IPv6 gateway address\n" "IPv6 gateway interface name\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL); +} + +DEFUN (no_ipv6_route_ifname_tag, + no_ipv6_route_ifname_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Set tag for this route\n" + "Tag value\n") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL); } ALIAS (no_ipv6_route_ifname, @@ -1497,6 +2118,20 @@ ALIAS (no_ipv6_route_ifname, "Emit an ICMP unreachable when matched\n" "Silently discard pkts when matched\n") +ALIAS (no_ipv6_route_ifname_tag, + no_ipv6_route_ifname_flags_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\n" + "Emit an ICMP unreachable when matched\n" + "Silently discard pkts when matched\n" + "Set tag for this route\n" + "Tag value\n") + DEFUN (no_ipv6_route_pref, no_ipv6_route_pref_cmd, "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255>", @@ -1508,7 +2143,23 @@ DEFUN (no_ipv6_route_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL, argv[2]); +} + +DEFUN (no_ipv6_route_pref_tag, + no_ipv6_route_pref_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\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") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2], argv[3]); } DEFUN (no_ipv6_route_flags_pref, @@ -1525,7 +2176,26 @@ DEFUN (no_ipv6_route_flags_pref, "Distance value for this prefix\n") { /* We do not care about argv[2] */ - return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], NULL, argv[3]); +} + +DEFUN (no_ipv6_route_flags_pref_tag, + no_ipv6_route_flags_pref_tag_cmd, + "no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\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") +{ + /* We do not care about argv[2] */ + return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], argv[4]); } DEFUN (no_ipv6_route_ifname_pref, @@ -1539,7 +2209,23 @@ DEFUN (no_ipv6_route_ifname_pref, "IPv6 gateway interface name\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, argv[3]); +} + +DEFUN (no_ipv6_route_ifname_pref_tag, + no_ipv6_route_ifname_pref_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\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") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]); } DEFUN (no_ipv6_route_ifname_flags_pref, @@ -1555,7 +2241,25 @@ DEFUN (no_ipv6_route_ifname_flags_pref, "Silently discard pkts when matched\n" "Distance value for this prefix\n") { - return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]); + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], NULL, argv[4]); +} + +DEFUN (no_ipv6_route_ifname_flags_pref_tag, + no_ipv6_route_ifname_flags_pref_tag_cmd, + "no ipv6 route X:X::X:X/M X:X::X:X INTERFACE (reject|blackhole) tag <1-65535> <1-255>", + NO_STR + IP_STR + "Establish static routes\n" + "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" + "IPv6 gateway address\n" + "IPv6 gateway interface name\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") +{ + return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } /* New RIB. Detailed information for IPv6 route. */ @@ -1575,6 +2279,8 @@ vty_show_ipv6_route_detail (struct vty *vty, struct route_node *rn) VTY_NEWLINE); vty_out (vty, " Known via \"%s\"", zebra_route_string (rib->type)); vty_out (vty, ", distance %u, metric %u", rib->distance, rib->metric); + if (rib->tag) + vty_out (vty, ", tag %d", rib->tag); if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) vty_out (vty, ", best"); if (rib->refcnt) @@ -1790,6 +2496,45 @@ DEFUN (show_ipv6_route, return CMD_SUCCESS; } +DEFUN (show_ipv6_route_tag, + show_ipv6_route_tag_cmd, + "show ipv6 route tag <1-65535>", + SHOW_STR + IP_STR + "IPv6 routing table\n" + "Show only routes with tag\n" + "Tag value\n") +{ + struct route_table *table; + struct route_node *rn; + struct rib *rib; + int first = 1; + u_short tag = 0; + + if (argv[0]) + tag = atoi(argv[0]); + + table = vrf_table (AFI_IP6, SAFI_UNICAST, 0); + if (! table) + return CMD_SUCCESS; + + /* Show all IPv6 routes with matching tag value. */ + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, rib) + { + if (rib->tag != tag) + continue; + + if (first) + { + vty_out (vty, SHOW_ROUTE_V6_HEADER); + first = 0; + } + vty_show_ipv6_route (vty, rn, rib); + } + return CMD_SUCCESS; +} + DEFUN (show_ipv6_route_prefix_longer, show_ipv6_route_prefix_longer_cmd, "show ipv6 route X:X::X:X/M longer-prefixes", @@ -2068,6 +2813,9 @@ static_config_ipv6 (struct vty *vty) if (CHECK_FLAG(si->flags, ZEBRA_FLAG_BLACKHOLE)) vty_out (vty, " %s", "blackhole"); + if (si->tag) + vty_out (vty, " tag %d", si->tag); + if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT) vty_out (vty, " %d", si->distance); vty_out (vty, "%s", VTY_NEWLINE); @@ -2102,30 +2850,56 @@ zebra_vty_init (void) install_node (&ip_node, zebra_ip_config); install_element (CONFIG_NODE, &ip_route_cmd); + install_element (CONFIG_NODE, &ip_route_tag_cmd); install_element (CONFIG_NODE, &ip_route_flags_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_cmd); install_element (CONFIG_NODE, &ip_route_flags2_cmd); + install_element (CONFIG_NODE, &ip_route_flags2_tag_cmd); install_element (CONFIG_NODE, &ip_route_mask_cmd); + install_element (CONFIG_NODE, &ip_route_mask_tag_cmd); install_element (CONFIG_NODE, &ip_route_mask_flags_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_cmd); install_element (CONFIG_NODE, &ip_route_mask_flags2_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags2_tag_cmd); install_element (CONFIG_NODE, &no_ip_route_cmd); + install_element (CONFIG_NODE, &no_ip_route_tag_cmd); install_element (CONFIG_NODE, &no_ip_route_flags_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_cmd); install_element (CONFIG_NODE, &no_ip_route_flags2_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags2_tag_cmd); install_element (CONFIG_NODE, &no_ip_route_mask_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_tag_cmd); install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_cmd); install_element (CONFIG_NODE, &no_ip_route_mask_flags2_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags2_tag_cmd); install_element (CONFIG_NODE, &ip_route_distance_cmd); + install_element (CONFIG_NODE, &ip_route_tag_distance_cmd); install_element (CONFIG_NODE, &ip_route_flags_distance_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_distance_cmd); install_element (CONFIG_NODE, &ip_route_flags_distance2_cmd); + install_element (CONFIG_NODE, &ip_route_flags_tag_distance2_cmd); install_element (CONFIG_NODE, &ip_route_mask_distance_cmd); + install_element (CONFIG_NODE, &ip_route_mask_tag_distance_cmd); install_element (CONFIG_NODE, &ip_route_mask_flags_distance_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_distance_cmd); install_element (CONFIG_NODE, &ip_route_mask_flags_distance2_cmd); + install_element (CONFIG_NODE, &ip_route_mask_flags_tag_distance2_cmd); install_element (CONFIG_NODE, &no_ip_route_distance_cmd); + install_element (CONFIG_NODE, &no_ip_route_tag_distance_cmd); install_element (CONFIG_NODE, &no_ip_route_flags_distance_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_distance_cmd); install_element (CONFIG_NODE, &no_ip_route_flags_distance2_cmd); + install_element (CONFIG_NODE, &no_ip_route_flags_tag_distance2_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_distance_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_tag_distance_cmd); install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_distance_cmd); install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance2_cmd); + install_element (CONFIG_NODE, &no_ip_route_mask_flags_tag_distance2_cmd); install_element (VIEW_NODE, &show_ip_route_cmd); + install_element (VIEW_NODE, &show_ip_route_tag_cmd); install_element (VIEW_NODE, &show_ip_nht_cmd); install_element (VIEW_NODE, &show_ipv6_nht_cmd); install_element (VIEW_NODE, &show_ip_route_addr_cmd); @@ -2136,6 +2910,7 @@ zebra_vty_init (void) install_element (VIEW_NODE, &show_ip_route_summary_cmd); install_element (VIEW_NODE, &show_ip_route_summary_prefix_cmd); install_element (ENABLE_NODE, &show_ip_route_cmd); + install_element (ENABLE_NODE, &show_ip_route_tag_cmd); install_element (ENABLE_NODE, &show_ip_nht_cmd); install_element (ENABLE_NODE, &show_ipv6_nht_cmd); install_element (ENABLE_NODE, &show_ip_route_addr_cmd); @@ -2167,7 +2942,24 @@ zebra_vty_init (void) install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_cmd); install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_cmd); install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_cmd); + install_element (CONFIG_NODE, &ipv6_route_tag_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_tag_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_tag_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_tag_cmd); + install_element (CONFIG_NODE, &ipv6_route_pref_tag_cmd); + install_element (CONFIG_NODE, &ipv6_route_flags_pref_tag_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_pref_tag_cmd); + install_element (CONFIG_NODE, &ipv6_route_ifname_flags_pref_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_pref_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_flags_pref_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_pref_tag_cmd); + install_element (CONFIG_NODE, &no_ipv6_route_ifname_flags_pref_tag_cmd); install_element (VIEW_NODE, &show_ipv6_route_cmd); + install_element (VIEW_NODE, &show_ipv6_route_tag_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_cmd); install_element (VIEW_NODE, &show_ipv6_route_summary_prefix_cmd); install_element (VIEW_NODE, &show_ipv6_route_protocol_cmd); @@ -2175,6 +2967,7 @@ zebra_vty_init (void) install_element (VIEW_NODE, &show_ipv6_route_prefix_cmd); install_element (VIEW_NODE, &show_ipv6_route_prefix_longer_cmd); install_element (ENABLE_NODE, &show_ipv6_route_cmd); + install_element (ENABLE_NODE, &show_ipv6_route_tag_cmd); install_element (ENABLE_NODE, &show_ipv6_route_protocol_cmd); install_element (ENABLE_NODE, &show_ipv6_route_addr_cmd); install_element (ENABLE_NODE, &show_ipv6_route_prefix_cmd); diff --git a/zebra/zserv.c b/zebra/zserv.c index f4ce81f78..471e2c668 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -588,6 +588,13 @@ zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, stream_putc (s, rib->distance); SET_FLAG (zapi_flags, ZAPI_MESSAGE_METRIC); stream_putl (s, rib->metric); + + /* tag */ + if (rib->tag) + { + SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG); + stream_putw(s, rib->tag); + } } /* write real message flags value */ @@ -1026,6 +1033,12 @@ zread_ipv4_add (struct zserv *client, u_short length) if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) rib->metric = stream_getl (s); + /* Tag */ + if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) + rib->tag = stream_getw (s); + else + rib->tag = 0; + /* Table */ rib->table=zebrad.rtm_table_default; rib_add_ipv4_multipath (&p, rib, safi); @@ -1109,6 +1122,12 @@ zread_ipv4_delete (struct zserv *client, u_short length) else api.metric = 0; + /* tag */ + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; + rib_delete_ipv4 (api.type, api.flags, &p, nexthop_p, ifindex, client->rtm_table, api.safi); return 0; @@ -1249,6 +1268,12 @@ zread_ipv6_add (struct zserv *client, u_short length) if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC)) rib->metric = stream_getl (s); + /* Tag */ + if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) + rib->tag = stream_getw (s); + else + rib->tag = 0; + /* Table */ rib->table=zebrad.rtm_table_default; rib_add_ipv6_multipath (&p, rib, safi, ifindex); @@ -1304,15 +1329,24 @@ zread_ipv6_delete (struct zserv *client, u_short length) } } + /* Distance. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; + + /* Metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; + /* tag */ + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; + if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, client->rtm_table, api.safi); else |