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 */