]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: enhance structures and esi and mac functions to handle EVPN
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 26 Oct 2016 10:21:53 +0000 (12:21 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 14 Feb 2017 12:58:57 +0000 (13:58 +0100)
EVPN introduces new objects to be handled: Ethernet Segment Identifier,
and MAC Address.
For Route type 5 message, it also involves gateway IP field that can be
either IPv4 or IPv6 address. This commit introduces those main structures.
It also introduces some functions to convert esi and mac address to
string, and vice-versa.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/Makefile.am
bgpd/bgp_attr_evpn.c [new file with mode: 0644]
bgpd/bgp_attr_evpn.h [new file with mode: 0644]

index 611dbb8558524e58a5fcee9d1c26dbab753bb527..4fda7adaab146d916da6cb38dbf1219057024d17 100644 (file)
@@ -79,7 +79,7 @@ libbgp_a_SOURCES = \
        bgp_mplsvpn.c bgp_nexthop.c \
        bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
         bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
-       bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC)
+       bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c
 
 noinst_HEADERS = \
        bgp_memory.h \
@@ -90,7 +90,7 @@ noinst_HEADERS = \
        bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
        bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \
         bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \
-       $(BGP_VNC_RFAPI_HD) 
+       $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h
 
 bgpd_SOURCES = bgp_main.c
 bgpd_LDADD = libbgp.a  $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
new file mode 100644 (file)
index 0000000..8715062
--- /dev/null
@@ -0,0 +1,262 @@
+/* Ethernet-VPN Attribute handling file
+   Copyright (C) 2016 6WIND
+
+This file is part of Free Range Routing.
+
+Free Range Routing is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Free Range Routing is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Free Range Routing; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "prefix.h"
+#include "log.h"
+#include "memory.h"
+#include "stream.h"
+
+#include "bgpd/bgp_attr_evpn.h"
+
+static uint8_t convertchartohexa (uint8_t *hexa, int *error)
+{
+  if( (*hexa == '0') || (*hexa == '1') || (*hexa == '2') ||
+      (*hexa == '3') || (*hexa == '4') || (*hexa == '5') ||
+      (*hexa == '6') || (*hexa == '7') || (*hexa == '8') ||
+      (*hexa == '9'))
+    return (uint8_t)(*hexa)-'0';
+  if((*hexa == 'a') || (*hexa == 'A'))
+    return 0xa;
+  if((*hexa == 'b') || (*hexa == 'B'))
+    return 0xb;
+  if((*hexa == 'c') || (*hexa == 'C'))
+    return 0xc;
+  if((*hexa == 'd') || (*hexa == 'D'))
+    return 0xd;
+  if((*hexa == 'e') || (*hexa == 'E'))
+    return 0xe;
+  if((*hexa == 'f') || (*hexa == 'F'))
+    return 0xf;
+  *error = -1;
+  return 0;
+}
+
+/* converts to internal representation of mac address
+ * returns 1 on success, 0 otherwise 
+ * format accepted: AA:BB:CC:DD:EE:FF
+ * if mac parameter is null, then check only
+ */
+int
+str2mac (const char *str, char *mac)
+{
+  unsigned int k=0, i, j;
+  uint8_t *ptr, *ptr2;
+  size_t len;
+  uint8_t car;
+
+  if (!str)
+    return 0;
+
+  if (str[0] == ':' && str[1] == '\0')
+    return 1;
+
+  i = 0;
+  ptr = (uint8_t *)str;
+  while (i < 6)
+    {
+      uint8_t temp[5];
+      int error = 0;
+      ptr2 = (uint8_t *)strchr((const char *)ptr, ':');
+      if (ptr2 == NULL)
+       {
+         /* if last occurence return ok */
+         if(i != 5)
+            {
+              zlog_err("[%s]: format non recognized",mac);
+              return 0;
+            }
+          len = strlen((char *)ptr);
+       } 
+      else
+        {
+          len = ptr2 - ptr;
+        }
+      if(len > 5)
+        {
+          zlog_err("[%s]: format non recognized",mac);
+         return 0;
+        }
+      memcpy(temp, ptr, len);
+      for(j=0;j< len;j++)
+       {
+         if (k >= MAC_LEN)
+           return 0;
+          if(mac)
+            mac[k] = 0;
+          car = convertchartohexa (&temp[j], &error);
+         if (error)
+           return 0;
+         if(mac)
+            mac[k] = car << 4;
+         j++;
+          if(j == len)
+            return 0;
+          car = convertchartohexa (&temp[j], &error) & 0xf;
+         if (error)
+           return 0;
+         if(mac)
+            mac[k] |= car & 0xf;
+         k++;
+         i++;
+       }
+      ptr = ptr2;
+      if(ptr == NULL)
+        break;
+      ptr++;
+    }
+  if(mac && 0)
+    {
+      zlog_err("leave correct : %02x:%02x:%02x:%02x:%02x:%02x",
+               mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff,
+               mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff);
+    }
+  return 1;
+}
+
+/* converts to an esi
+ * returns 1 on success, 0 otherwise
+ * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
+ * if id is null, check only is done
+ */
+int
+str2esi (const char *str, struct eth_segment_id *id)
+{
+  unsigned int k=0, i, j;
+  uint8_t *ptr, *ptr2;
+  size_t len;
+  uint8_t car;
+
+  if (!str)
+    return 0;
+  if (str[0] == ':' && str[1] == '\0')
+    return 1;
+
+  i = 0;
+  ptr = (uint8_t *)str;
+  while (i < 10)
+    {
+      uint8_t temp[5];
+      int error = 0;
+      ptr2 = (uint8_t *)strchr((const char *)ptr, ':');
+      if (ptr2 == NULL)
+       {
+         /* if last occurence return ok */
+         if(i != 9)
+            {
+              zlog_err("[%s]: format non recognized",str);
+              return 0;
+            }
+          len = strlen((char *)ptr);
+       }
+      else
+        {
+          len = ptr2 - ptr;
+        }
+      memcpy(temp, ptr, len);
+      if(len > 5)
+        {
+          zlog_err("[%s]: format non recognized",str);
+         return 0;
+        }
+      for(j=0;j< len;j++)
+       {
+         if (k >= ESI_LEN)
+           return 0;
+          if(id)
+            id->val[k] = 0;
+          car = convertchartohexa (&temp[j], &error);
+          if (error)
+            return 0;
+          if(id)
+            id->val[k] = car << 4;
+          j++;
+          if(j == len)
+            return 0;
+          car = convertchartohexa (&temp[j], &error) & 0xf;
+          if (error)
+            return 0;
+          if(id)
+            id->val[k] |= car & 0xf;
+         k++;
+         i++;
+       }
+      ptr = ptr2;
+      if(ptr == NULL)
+        break;
+      ptr++;
+    }
+  if(id && 0)
+    {
+      zlog_err("leave correct : %02x:%02x:%02x:%02x:%02x",
+               id->val[0], id->val[1], id->val[2], id->val[3], id->val[4]);
+      zlog_err("%02x:%02x:%02x:%02x:%02x",
+               id->val[5], id->val[6], id->val[7], id->val[8], id->val[9]);
+    }
+  return 1;
+}
+
+char *
+esi2str (struct eth_segment_id *id)
+{
+  char *ptr;
+  u_char *val;
+
+  if(!id)
+    return NULL;
+
+  val = id->val;
+  ptr = (char *) malloc ((ESI_LEN*2+ESI_LEN-1+1)*sizeof(char));
+
+  snprintf (ptr, (ESI_LEN*2+ESI_LEN-1+1),
+            "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+            val[0], val[1], val[2], val[3], val[4],
+            val[5], val[6], val[7], val[8], val[9]);
+
+  return ptr;
+}
+
+char *
+mac2str (char *mac)
+{
+  char *ptr;
+
+  if(!mac)
+    return NULL;
+
+  ptr = (char *) malloc ((MAC_LEN*2+MAC_LEN-1+1)*sizeof(char));
+
+  snprintf (ptr, (MAC_LEN*2+MAC_LEN-1+1), "%02x:%02x:%02x:%02x:%02x:%02x",
+           (uint8_t) mac[0], (uint8_t)mac[1], (uint8_t)mac[2], (uint8_t)mac[3],
+           (uint8_t)mac[4], (uint8_t)mac[5]);
+
+  return ptr;
+}
+
+char *ecom_mac2str(char *ecom_mac)
+{
+  char *en;
+
+  en = ecom_mac;
+  en+=2;
+  return mac2str(en);
+}
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
new file mode 100644 (file)
index 0000000..14846eb
--- /dev/null
@@ -0,0 +1,55 @@
+/* E-VPN attribute handling structure file
+   Copyright (C) 2016 6WIND
+
+This file is part of Free Range Routing.
+
+Free Range Routing is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Free Range Routing is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Free Range Routing; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#ifndef _QUAGGA_BGP_ATTR_EVPN_H
+#define _QUAGGA_BGP_ATTR_EVPN_H
+
+/* value of first byte of ESI */
+#define ESI_TYPE_ARBITRARY 0 /* */
+#define ESI_TYPE_LACP      1 /* <> */
+#define ESI_TYPE_BRIDGE    2 /* <Root bridge Mac-6B>:<Root Br Priority-2B>:00 */
+#define ESI_TYPE_MAC       3 /* <Syst Mac Add-6B>:<Local Discriminator Value-3B> */
+#define ESI_TYPE_ROUTER    4 /* <RouterId-4B>:<Local Discriminator Value-4B> */
+#define ESI_TYPE_AS        5 /* <AS-4B>:<Local Discriminator Value-4B> */
+#define MAX_ESI {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
+#define ESI_LEN 10
+
+#define MAX_ET 0xffffffff
+u_long eth_tag_id;
+
+struct eth_segment_id
+{
+  u_char val[ESI_LEN];
+};
+
+#define MAC_LEN 6
+
+union gw_addr {
+  struct in_addr ipv4;
+  struct in6_addr ipv6;
+};
+
+extern int str2esi (const char *str, struct eth_segment_id *id);
+extern int str2mac (const char *str, char *mac);
+extern char *esi2str (struct eth_segment_id *id);
+extern char *mac2str (char *mac);
+extern char *ecom_mac2str(char *ecom_mac);
+
+#endif /* _QUAGGA_BGP_ATTR_EVPN_H */