bgpd: handle AS4 and EOI route distinguishers

Signed-off-by: Lou Berger <lberger@labn.net>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 3eab76f..bbc739b 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -54,6 +54,7 @@
   return l;
 }
 
+/* type == RD_TYPE_AS */
 static void
 decode_rd_as (u_char *pnt, struct rd_as *rd_as)
 {
@@ -66,6 +67,20 @@
   rd_as->val |= (u_int32_t) *pnt;
 }
 
+/* type == RD_TYPE_AS4 */
+static void
+decode_rd_as4 (u_char *pnt, struct rd_as *rd_as)
+{
+  rd_as->as  = (u_int32_t) *pnt++ << 24;
+  rd_as->as |= (u_int32_t) *pnt++ << 16;
+  rd_as->as |= (u_int32_t) *pnt++ << 8;
+  rd_as->as |= (u_int32_t) *pnt++;
+
+  rd_as->val  = ((u_int16_t) *pnt++ << 8);
+  rd_as->val |= (u_int16_t) *pnt;
+}
+
+/* type == RD_TYPE_IP */
 static void
 decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
 {
@@ -149,30 +164,32 @@
       /* Decode RD type. */
       type = decode_rd_type (pnt + 3);
 
-      /* Decode RD value. */
-      if (type == RD_TYPE_AS)
-	decode_rd_as (pnt + 5, &rd_as);
-      else if (type == RD_TYPE_IP)
-	decode_rd_ip (pnt + 5, &rd_ip);
-      else
-	{
-	  zlog_err ("Invalid RD type %d", type);
-	  return -1;
-	}
+      switch (type)
+        {
+        case RD_TYPE_AS:
+          decode_rd_as (pnt + 5, &rd_as);
+          break;
+
+        case RD_TYPE_AS4:
+          decode_rd_as4 (pnt + 5, &rd_as);
+          break;
+
+        case RD_TYPE_IP:
+          decode_rd_ip (pnt + 5, &rd_ip);
+          break;
+
+        case RD_TYPE_EOI:
+          break;
+
+        default:
+          zlog_err ("Invalid RD type %d", type);
+          return -1;
+        }
 
       p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8;
       memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, 
               psize - VPN_PREFIXLEN_MIN_BYTES);
 
-#if 0
-      if (type == RD_TYPE_AS)
-	zlog_info ("prefix %ld:%ld:%ld:%s/%d", label, rd_as.as, rd_as.val,
-		   inet_ntoa (p.u.prefix4), p.prefixlen);
-      else if (type == RD_TYPE_IP)
-	zlog_info ("prefix %ld:%s:%ld:%s/%d", label, inet_ntoa (rd_ip.ip),
-		   rd_ip.val, inet_ntoa (p.u.prefix4), p.prefixlen);
-#endif /* 0 */
-
       if (attr)
 	bgp_update (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
 		    ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
@@ -294,12 +311,25 @@
       snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
       return buf;
     }
+  else if (type == RD_TYPE_AS4)
+    {
+      decode_rd_as4 (pnt + 2, &rd_as);
+      snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val);
+      return buf;
+    }
   else if (type == RD_TYPE_IP)
     {
       decode_rd_ip (pnt + 2, &rd_ip);
       snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
       return buf;
     }
+  else if (type == RD_TYPE_EOI)
+    {
+      snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
+               pnt[1], /* LHI */
+               pnt[2], pnt[3], pnt[4], pnt[5], pnt[6], pnt[7]); /* MAC */
+      return buf;
+    }
 
   return NULL;
 }
@@ -406,6 +436,8 @@
                     /* Decode RD value. */
                     if (type == RD_TYPE_AS)
                       decode_rd_as (pnt + 2, &rd_as);
+                    else if (type == RD_TYPE_AS4)
+                      decode_rd_as4 (pnt + 2, &rd_as);
                     else if (type == RD_TYPE_IP)
                       decode_rd_ip (pnt + 2, &rd_ip);
 
@@ -413,6 +445,8 @@
 
                     if (type == RD_TYPE_AS)
                       vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
+                    else if (type == RD_TYPE_AS4)
+                      vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
                     else if (type == RD_TYPE_IP)
                       vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
 
@@ -513,15 +547,19 @@
 		    /* Decode RD value. */
 		    if (type == RD_TYPE_AS)
 		      decode_rd_as (pnt + 2, &rd_as);
+		    else if (type == RD_TYPE_AS4)
+		      decode_rd_as4 (pnt + 2, &rd_as);
 		    else if (type == RD_TYPE_IP)
 		      decode_rd_ip (pnt + 2, &rd_ip);
 
 		    vty_out (vty, "Route Distinguisher: ");
 
 		    if (type == RD_TYPE_AS)
-		      vty_out (vty, "%u:%d", rd_as.as, rd_as.val);
+		      vty_out (vty, "as2 %u:%d", rd_as.as, rd_as.val);
+		    else if (type == RD_TYPE_AS4)
+		      vty_out (vty, "as4 %u:%d", rd_as.as, rd_as.val);
 		    else if (type == RD_TYPE_IP)
-		      vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
+		      vty_out (vty, "ip %s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
 		  
 		    vty_out (vty, "%s", VTY_NEWLINE);		  
 		    rd_header = 0;