back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_attr_evpn.c (source / functions) Hit Total Coverage
Test: test_bgp_minimum_holdtime.py::TestBGPMinimumHoldtime Lines: 0 143 0.0 %
Date: 2023-02-24 18:37:25 Functions: 0 10 0.0 %

          Line data    Source code
       1             : /* Ethernet-VPN Attribute handling file
       2             :  * Copyright (C) 2016 6WIND
       3             :  *
       4             :  * This file is part of FRRouting.
       5             :  *
       6             :  * FRRouting is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * FRRouting is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "command.h"
      24             : #include "filter.h"
      25             : #include "prefix.h"
      26             : #include "log.h"
      27             : #include "memory.h"
      28             : #include "stream.h"
      29             : #include "vxlan.h"
      30             : 
      31             : #include "bgpd/bgpd.h"
      32             : #include "bgpd/bgp_attr.h"
      33             : #include "bgpd/bgp_route.h"
      34             : #include "bgpd/bgp_attr_evpn.h"
      35             : #include "bgpd/bgp_ecommunity.h"
      36             : #include "bgpd/bgp_evpn.h"
      37             : #include "bgpd/bgp_evpn_private.h"
      38             : 
      39           0 : bool bgp_route_evpn_same(const struct bgp_route_evpn *e1,
      40             :                          const struct bgp_route_evpn *e2)
      41             : {
      42           0 :         return (e1->type == e2->type &&
      43           0 :                 !memcmp(&(e1->eth_s_id), &(e2->eth_s_id), sizeof(esi_t)) &&
      44           0 :                 !ipaddr_cmp(&(e1->gw_ip), &(e2->gw_ip)));
      45             : }
      46             : 
      47           0 : void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
      48             : {
      49           0 :         struct ecommunity_val routermac_ecom;
      50           0 :         struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
      51             : 
      52           0 :         memset(&routermac_ecom, 0, sizeof(routermac_ecom));
      53           0 :         routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
      54           0 :         routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
      55           0 :         memcpy(&routermac_ecom.val[2], routermac->octet, ETH_ALEN);
      56           0 :         if (!ecomm) {
      57           0 :                 bgp_attr_set_ecommunity(attr, ecommunity_new());
      58             :                 ecomm = bgp_attr_get_ecommunity(attr);
      59             :         }
      60           0 :         ecommunity_add_val(ecomm, &routermac_ecom, false, false);
      61           0 :         ecommunity_str(ecomm);
      62           0 : }
      63             : 
      64             : /* converts to an esi
      65             :  * returns 1 on success, 0 otherwise
      66             :  * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
      67             :  * if id is null, check only is done
      68             :  */
      69           0 : bool str2esi(const char *str, esi_t *id)
      70             : {
      71           0 :         unsigned int a[ESI_BYTES];
      72           0 :         int i;
      73             : 
      74           0 :         if (!str)
      75             :                 return false;
      76           0 :         if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1,
      77             :                    a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9)
      78             :             != ESI_BYTES) {
      79             :                 /* error in incoming str length */
      80             :                 return false;
      81             :         }
      82             :         /* valid mac address */
      83           0 :         if (!id)
      84             :                 return true;
      85           0 :         for (i = 0; i < ESI_BYTES; ++i)
      86           0 :                 id->val[i] = a[i] & 0xff;
      87             :         return true;
      88             : }
      89             : 
      90           0 : char *ecom_mac2str(char *ecom_mac)
      91             : {
      92           0 :         char *en;
      93             : 
      94           0 :         en = ecom_mac;
      95           0 :         en += 2;
      96             : 
      97           0 :         return prefix_mac2str((struct ethaddr *)en, NULL, 0);
      98             : }
      99             : 
     100             : /* Fetch router-mac from extended community */
     101           0 : bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
     102             : {
     103           0 :         uint32_t i = 0;
     104           0 :         struct ecommunity *ecom;
     105             : 
     106           0 :         ecom = bgp_attr_get_ecommunity(attr);
     107           0 :         if (!ecom || !ecom->size)
     108             :                 return false;
     109             : 
     110             :         /* If there is a router mac extended community, set RMAC in attr */
     111           0 :         for (i = 0; i < ecom->size; i++) {
     112           0 :                 uint8_t *pnt = NULL;
     113           0 :                 uint8_t type = 0;
     114           0 :                 uint8_t sub_type = 0;
     115             : 
     116           0 :                 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
     117           0 :                 type = *pnt++;
     118           0 :                 sub_type = *pnt++;
     119             : 
     120           0 :                 if (!(type == ECOMMUNITY_ENCODE_EVPN
     121           0 :                       && sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
     122           0 :                         continue;
     123             : 
     124           0 :                 memcpy(rmac, pnt, ETH_ALEN);
     125           0 :                 return true;
     126             :         }
     127             :         return false;
     128             : }
     129             : 
     130             : /*
     131             :  * return true if attr contains default gw extended community
     132             :  */
     133           0 : uint8_t bgp_attr_default_gw(struct attr *attr)
     134             : {
     135           0 :         struct ecommunity *ecom;
     136           0 :         uint32_t i;
     137             : 
     138           0 :         ecom = bgp_attr_get_ecommunity(attr);
     139           0 :         if (!ecom || !ecom->size)
     140             :                 return 0;
     141             : 
     142             :         /* If there is a default gw extendd community return true otherwise
     143             :          * return 0 */
     144           0 :         for (i = 0; i < ecom->size; i++) {
     145           0 :                 uint8_t *pnt;
     146           0 :                 uint8_t type, sub_type;
     147             : 
     148           0 :                 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
     149           0 :                 type = *pnt++;
     150           0 :                 sub_type = *pnt++;
     151             : 
     152           0 :                 if ((type == ECOMMUNITY_ENCODE_OPAQUE
     153           0 :                      && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
     154             :                         return 1;
     155             :         }
     156             : 
     157             :         return 0;
     158             : }
     159             : 
     160             : /*
     161             :  * Fetch and return the DF preference and algorithm from
     162             :  * DF election extended community, if present, else 0.
     163             :  */
     164           0 : uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg)
     165             : {
     166           0 :         struct ecommunity *ecom;
     167           0 :         uint32_t i;
     168           0 :         uint16_t df_pref = 0;
     169             : 
     170           0 :         *alg = EVPN_MH_DF_ALG_SERVICE_CARVING;
     171           0 :         ecom = bgp_attr_get_ecommunity(attr);
     172           0 :         if (!ecom || !ecom->size)
     173             :                 return 0;
     174             : 
     175           0 :         for (i = 0; i < ecom->size; i++) {
     176           0 :                 uint8_t *pnt;
     177           0 :                 uint8_t type, sub_type;
     178             : 
     179           0 :                 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
     180           0 :                 type = *pnt++;
     181           0 :                 sub_type = *pnt++;
     182           0 :                 if (!(type == ECOMMUNITY_ENCODE_EVPN
     183           0 :                       && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION))
     184           0 :                         continue;
     185             : 
     186           0 :                 *alg = (*pnt++) & ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS;
     187             : 
     188           0 :                 pnt += 3;
     189           0 :                 pnt = ptr_get_be16(pnt, &df_pref);
     190           0 :                 (void)pnt; /* consume value */
     191           0 :                 break;
     192             :         }
     193             : 
     194             :         return df_pref;
     195             : }
     196             : 
     197             : /*
     198             :  * Fetch and return the sequence number from MAC Mobility extended
     199             :  * community, if present, else 0.
     200             :  */
     201           0 : uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
     202             : {
     203           0 :         struct ecommunity *ecom;
     204           0 :         uint32_t i;
     205           0 :         uint8_t flags = 0;
     206             : 
     207           0 :         ecom = bgp_attr_get_ecommunity(attr);
     208           0 :         if (!ecom || !ecom->size)
     209             :                 return 0;
     210             : 
     211             :         /* If there is a MAC Mobility extended community, return its
     212             :          * sequence number.
     213             :          * TODO: RFC is silent on handling of multiple MAC mobility extended
     214             :          * communities for the same route. We will bail out upon the first
     215             :          * one.
     216             :          */
     217           0 :         for (i = 0; i < ecom->size; i++) {
     218           0 :                 const uint8_t *pnt;
     219           0 :                 uint8_t type, sub_type;
     220           0 :                 uint32_t seq_num;
     221             : 
     222           0 :                 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
     223           0 :                 type = *pnt++;
     224           0 :                 sub_type = *pnt++;
     225           0 :                 if (!(type == ECOMMUNITY_ENCODE_EVPN
     226           0 :                       && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
     227           0 :                         continue;
     228           0 :                 flags = *pnt++;
     229             : 
     230           0 :                 if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
     231           0 :                         *sticky = 1;
     232             :                 else
     233           0 :                         *sticky = 0;
     234             : 
     235           0 :                 pnt++;
     236           0 :                 pnt = ptr_get_be32(pnt, &seq_num);
     237           0 :                 (void)pnt; /* consume value */
     238           0 :                 return seq_num;
     239             :         }
     240             : 
     241             :         return 0;
     242             : }
     243             : 
     244             : /*
     245             :  * return true if attr contains router flag extended community
     246             :  */
     247           0 : void bgp_attr_evpn_na_flag(struct attr *attr,
     248             :                 uint8_t *router_flag, bool *proxy)
     249             : {
     250           0 :         struct ecommunity *ecom;
     251           0 :         uint32_t i;
     252           0 :         uint8_t val;
     253             : 
     254           0 :         ecom = bgp_attr_get_ecommunity(attr);
     255           0 :         if (!ecom || !ecom->size)
     256             :                 return;
     257             : 
     258             :         /* If there is a evpn na extendd community set router_flag */
     259           0 :         for (i = 0; i < ecom->size; i++) {
     260           0 :                 uint8_t *pnt;
     261           0 :                 uint8_t type, sub_type;
     262             : 
     263           0 :                 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
     264           0 :                 type = *pnt++;
     265           0 :                 sub_type = *pnt++;
     266             : 
     267           0 :                 if (type == ECOMMUNITY_ENCODE_EVPN &&
     268           0 :                     sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
     269           0 :                         val = *pnt++;
     270             : 
     271           0 :                         if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG)
     272           0 :                                 *router_flag = 1;
     273             : 
     274           0 :                         if (val & ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG)
     275           0 :                                 *proxy = true;
     276             : 
     277             :                         break;
     278             :                 }
     279             :         }
     280             : }
     281             : 
     282             : /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
     283           0 : extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
     284             :                                  struct prefix *dst)
     285             : {
     286           0 :         struct evpn_addr *p_evpn_p;
     287           0 :         struct prefix p2;
     288           0 :         struct prefix *src = &p2;
     289             : 
     290           0 :         if (!dst || dst->family == 0)
     291             :                 return -1;
     292             :         /* store initial prefix in src */
     293           0 :         prefix_copy(src, dst);
     294           0 :         memset(dst, 0, sizeof(struct prefix));
     295           0 :         p_evpn_p = &(dst->u.prefix_evpn);
     296           0 :         dst->family = AF_EVPN;
     297           0 :         p_evpn_p->route_type = evpn_type;
     298           0 :         if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
     299           0 :                 p_evpn_p->prefix_addr.eth_tag = eth_tag;
     300           0 :                 p_evpn_p->prefix_addr.ip_prefix_length = p2.prefixlen;
     301           0 :                 if (src->family == AF_INET) {
     302           0 :                         SET_IPADDR_V4(&p_evpn_p->prefix_addr.ip);
     303           0 :                         memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
     304             :                                &src->u.prefix4,
     305             :                                sizeof(struct in_addr));
     306           0 :                         dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
     307             :                 } else {
     308           0 :                         SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
     309           0 :                         memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
     310             :                                &src->u.prefix6,
     311             :                                sizeof(struct in6_addr));
     312           0 :                         dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
     313             :                 }
     314             :         } else
     315             :                 return -1;
     316             :         return 0;
     317             : }

Generated by: LCOV version v1.16-topotato