summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 02:46:33 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-05-20 02:46:33 +0200
commit0d9551dc3c53f2d46e3c0e3ecb4e4b0eb327179e (patch)
treef8bf3ba86e81b823af3fcb6fcf1f4fbe77c0b167
parentbgpd-fix-nexthop-show.patch (diff)
downloadfrr-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.c3
-rw-r--r--bgpd/bgp_attr.h3
-rw-r--r--bgpd/bgp_route.c8
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_routemap.c211
-rw-r--r--bgpd/bgp_zebra.c94
-rw-r--r--lib/zclient.c6
-rw-r--r--lib/zclient.h5
-rw-r--r--ospfd/ospf_asbr.c5
-rw-r--r--ospfd/ospf_asbr.h3
-rw-r--r--ospfd/ospf_lsa.c6
-rw-r--r--ospfd/ospf_routemap.c192
-rw-r--r--ospfd/ospf_zebra.c23
-rw-r--r--ospfd/ospfd.c1
-rw-r--r--ospfd/ospfd.h3
-rw-r--r--ripd/rip_routemap.c23
-rw-r--r--ripngd/ripng_routemap.c8
-rw-r--r--zebra/rib.h20
-rw-r--r--zebra/zebra_rib.c42
-rw-r--r--zebra/zebra_vty.c885
-rw-r--r--zebra/zserv.c34
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