bgpd, lib, ospfd, zebra: Add ability to read/write tag value

Modify zebra to pass the tag value to and from the
various protocols.

[forward ported by Cumulus]

Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
Signed-off-by: Piotr Chytla <pch@packetconsulting.pl>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Edits: Paul Jakma <paul.jakma@hpe.com> rebase conflicts in bgp_zebra.c
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index b9e8a5c..5283d74 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -278,17 +278,23 @@
   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,
 			   api.metric, api.type);
@@ -299,12 +305,13 @@
 	{
 	  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);
     }
@@ -358,6 +365,11 @@
   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;
@@ -367,12 +379,13 @@
       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,
 			    api.metric, api.type);
@@ -383,12 +396,13 @@
 	{
 	  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);
     }
@@ -680,6 +694,7 @@
   struct bgp_info *mpinfo;
   size_t oldsize, newsize;
   u_int32_t nhcount;
+  u_short tag = 0;
 
   if (zclient->sock < 0)
     return;
@@ -742,6 +757,12 @@
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
 
+      if (tag)
+	{
+	  SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
+	  api.tag = tag;
+	}
+
       distance = bgp_distance_apply (p, info, bgp);
 
       if (distance)
@@ -755,11 +776,11 @@
 	  int i;
 	  char buf[2][INET_ADDRSTRLEN];
 	  zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u"
-		     " count %d",
+	             " tag %u count %d",
 		     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
 		     p->prefixlen,
 		     inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
-		     api.metric, api.nexthop_num);
+		     api.metric, api.tag, api.nexthop_num);
 	  for (i = 1; i < api.nexthop_num; i++)
 	    zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s",
 		       i, inet_ntop(AF_INET, api.nexthop[i], buf[1],
@@ -921,15 +942,22 @@
           SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
           api.distance = distance;
         }
+      
+      if (tag)
+	{
+	  SET_FLAG (api.message, ZAPI_MESSAGE_TAG);
+	  api.tag = tag;
+	}
 
       if (BGP_DEBUG(zebra, ZEBRA))
 	{
 	  char buf[2][INET6_ADDRSTRLEN];
-	  zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u",
+	  zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u"
+                     " tag %u",
 		     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_ADD, zclient, 
diff --git a/lib/zclient.c b/lib/zclient.c
index 097314a..a1de831 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -530,6 +530,8 @@
   * 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
@@ -588,6 +590,8 @@
     stream_putl (s, api->metric);
   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
     stream_putl (s, api->mtu);
+  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));
@@ -644,6 +648,8 @@
     stream_putl (s, api->metric);
   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_MTU))
     stream_putl (s, api->mtu);
+  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 a3452eb..810c927 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -99,6 +99,7 @@
 #define ZAPI_MESSAGE_DISTANCE 0x04
 #define ZAPI_MESSAGE_METRIC   0x08
 #define ZAPI_MESSAGE_MTU      0x10
+#define ZAPI_MESSAGE_TAG      0x20
 
 /* Zserv protocol message header */
 struct zserv_header
@@ -132,6 +133,8 @@
 
   u_char distance;
 
+  u_short tag;
+
   u_int32_t metric;
 
   u_int32_t mtu;
@@ -210,6 +213,8 @@
 
   u_char distance;
 
+  u_short tag;
+
   u_int32_t metric;
 
   u_int32_t mtu;
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 3e35979..d9b0837 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -545,6 +545,7 @@
       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);
 
@@ -569,6 +570,7 @@
       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);
 
@@ -888,6 +890,10 @@
     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)
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 6e65aa1..89232c2 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -494,6 +494,12 @@
       stream_putl (s, rib->metric);
       SET_FLAG (zapi_flags, ZAPI_MESSAGE_MTU);
       stream_putl (s, rib->mtu);
+      /* tag */
+      if (rib->tag)
+        {
+          SET_FLAG(zapi_flags, ZAPI_MESSAGE_TAG);
+          stream_putw(s, rib->tag);
+        }
     }
   
   /* write real message flags value */
@@ -1003,6 +1009,9 @@
     
   if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
     rib->mtu = stream_getl (s);
+  /* Tag */
+  if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG))
+    rib->tag = stream_getw (s);
 
   /* Table */
   rib->table=zebrad.rtm_table_default;
@@ -1087,6 +1096,12 @@
   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,
                    vrf_id, api.safi);
   return 0;
@@ -1234,6 +1249,10 @@
   if (CHECK_FLAG (message, ZAPI_MESSAGE_MTU))
     rib->mtu = stream_getl (s);
 
+  /* Tag */
+  if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG))
+    rib->tag = stream_getw (s);
+
   /* Table */
   rib->table=zebrad.rtm_table_default;
   rib_add_ipv6_multipath (&p, rib, safi);
@@ -1289,15 +1308,24 @@
 	}
     }
 
+  /* 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, vrf_id,
                      api.safi);