zebra: Add internal support for route tags

Add internal support for a route tag to be applied to routes.
At this point in time, tags are not being used.

[forward ported by Cumulus]

Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
Signed-off-by: Piotr Chytła <pch@packetconsulting.pl>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Edited-by: Paul Jakma <paul.jakma@hpe.com> - rebase conflicts
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index a55d358..e57d1af 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2147,6 +2147,10 @@
 
   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);
@@ -2184,6 +2188,7 @@
       rib->vrf_id = si->vrf_id;
       rib->table = zebrad.rtm_table_default;
       rib->nexthop_num = 0;
+      rib->tag = si->tag;
 
       switch (si->type)
         {
@@ -2269,7 +2274,8 @@
       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;
     }
 
@@ -2308,7 +2314,7 @@
 
 int
 static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
-		      const char *ifname, u_char flags, u_char distance,
+		      const char *ifname, u_char flags, u_short tag, u_char distance,
 		      vrf_id_t vrf_id)
 {
   u_char type = 0;
@@ -2341,7 +2347,8 @@
 	  && (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
 	  && (! ifname || strcmp (ifname, si->ifname) == 0))
 	{
-	  if (distance == si->distance)
+	  if (distance == si->distance &&
+	      tag == si->tag)
 	    {
 	      route_unlock_node (rn);
 	      return 0;
@@ -2351,15 +2358,16 @@
 	}
     }
 
-  /* Distance changed.  */
+  /* Distance or tag changed. */
   if (update)
-    static_delete_ipv4_safi (safi, p, gate, ifname, update->distance, vrf_id);
+    static_delete_ipv4_safi (safi, p, gate, ifname, update->tag, update->distance, vrf_id);
 
   /* Make new static route structure. */
   si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
 
   si->type = type;
   si->distance = distance;
+  si->tag = tag;
   si->flags = flags;
   si->vrf_id = vrf_id;
 
@@ -2403,7 +2411,7 @@
 
 int
 static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
-			 const char *ifname, u_char distance, vrf_id_t vrf_id)
+			 const char *ifname, u_short tag, u_char distance, vrf_id_t vrf_id)
 {
   u_char type = 0;
   struct route_node *rn;
@@ -2432,7 +2440,8 @@
   for (si = rn->info; si; si = si->next)
     if (type == si->type
 	&& (! gate || IPV4_ADDR_SAME (gate, &si->addr.ipv4))
-	&& (! ifname || strcmp (ifname, si->ifname) == 0))
+	&& (! ifname || strcmp (ifname, si->ifname) == 0)
+	&& (! tag || (tag == si->tag)))
       break;
 
   /* Can't find static route. */
@@ -2788,8 +2797,8 @@
 /* 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,
-		 vrf_id_t vrf_id)
+		 const char *ifname, u_char flags, u_short tag,
+		 u_char distance, vrf_id_t vrf_id)
 {
   struct route_node *rn;
   struct static_route *si;
@@ -2817,6 +2826,7 @@
   for (si = rn->info; si; si = si->next)
     {
       if (type == si->type
+	  && tag == si->tag
 	  && (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
 	  && (! ifname || strcmp (ifname, si->ifname) == 0))
 	{
@@ -2831,13 +2841,14 @@
     }
 
   if (update)
-    static_delete_ipv6(p, type, gate, ifname, si->distance, vrf_id);
+    static_delete_ipv6(p, type, gate, ifname, tag, si->distance, vrf_id);
 
   /* Make new static route structure. */
   si = XCALLOC (MTYPE_STATIC_ROUTE, sizeof (struct static_route));
 
   si->type = type;
   si->distance = distance;
+  si->tag = tag;
   si->flags = flags;
   si->vrf_id = vrf_id;
 
@@ -2884,7 +2895,7 @@
 /* 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, vrf_id_t vrf_id)
+		    const char *ifname, u_short tag, u_char distance, vrf_id_t vrf_id)
 {
   struct route_node *rn;
   struct static_route *si;
@@ -2905,7 +2916,8 @@
     if (distance == si->distance 
 	&& type == si->type
 	&& (! gate || IPV6_ADDR_SAME (gate, &si->addr.ipv6))
-	&& (! ifname || strcmp (ifname, si->ifname) == 0))
+	&& (! ifname || strcmp (ifname, si->ifname) == 0)
+	&& (! tag || (tag == si->tag)))
       break;
 
   /* Can't find static route. */