Mailing List Archive

[PATCH 25/57] bgpd: enhance structures and esi and mac functions to handle EVPN
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 | 5 +-
bgpd/bgp_attr_evpn.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++
bgpd/bgp_attr_evpn.h | 57 +++++++++++
3 files changed, 322 insertions(+), 2 deletions(-)
create mode 100644 bgpd/bgp_attr_evpn.c
create mode 100644 bgpd/bgp_attr_evpn.h

diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index fe1be32edb37..a2ebe2dcd8cc 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -16,7 +16,7 @@ libbgp_a_SOURCES = \
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
- bgp_encap.c bgp_encap_tlv.c bgp_nht.c
+ bgp_encap.c bgp_encap_tlv.c bgp_nht.c bgp_attr_evpn.c

noinst_HEADERS = \
bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
@@ -24,7 +24,8 @@ noinst_HEADERS = \
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
bgp_ecommunity.h 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_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h
+ bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h bgp_nht.h \
+ bgp_attr_evpn.h

bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a ../lib/libzebra.la @LIBCAP@ @LIBM@
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
new file mode 100644
index 000000000000..9a092a11ff21
--- /dev/null
+++ b/bgpd/bgp_attr_evpn.c
@@ -0,0 +1,262 @@
+/* Ethernet-VPN Attribute handling file
+ Copyright (C) 2016 6WIND
+
+This file is part of GNU Quagga
+
+GNU Zebra 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.
+
+GNU Zebra 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 GNU Zebra; 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
index 000000000000..1f5e579a0f00
--- /dev/null
+++ b/bgpd/bgp_attr_evpn.h
@@ -0,0 +1,57 @@
+/* E-VPN attribute handling structure file
+ Copyright (C) 2016 6WIND
+
+This file is part of GNU Quagga.
+
+GNU Quagga 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.
+
+GNU Quagga 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 GNU Quagga; 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;
+#ifdef HAVE_IPV6
+ struct in6_addr ipv6;
+#endif /* HAVE_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 */
--
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev