From: Philippe Guibert Date: Wed, 26 Oct 2016 10:21:53 +0000 (+0200) Subject: bgpd: enhance structures and esi and mac functions to handle EVPN X-Git-Tag: frr-3.0-branchpoint~29^2~53 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=212f5cbcedd477a4652a880f86eddd3b304ea7e5;p=mirror%2Ffrr.git 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 --- diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 611dbb8558..4fda7adaab 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -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 index 0000000000..8715062bae --- /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 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 + +#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 0000000000..14846ebc1f --- /dev/null +++ b/bgpd/bgp_attr_evpn.h @@ -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 /* ::00 */ +#define ESI_TYPE_MAC 3 /* : */ +#define ESI_TYPE_ROUTER 4 /* : */ +#define ESI_TYPE_AS 5 /* : */ +#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 */