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

          Line data    Source code
       1             : /* BGP carrying label information
       2             :  * Copyright (C) 2013 Cumulus Networks, Inc.
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra 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             :  * GNU Zebra 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 "thread.h"
      25             : #include "prefix.h"
      26             : #include "zclient.h"
      27             : #include "stream.h"
      28             : #include "network.h"
      29             : #include "log.h"
      30             : #include "memory.h"
      31             : #include "nexthop.h"
      32             : #include "mpls.h"
      33             : 
      34             : #include "bgpd/bgpd.h"
      35             : #include "bgpd/bgp_table.h"
      36             : #include "bgpd/bgp_route.h"
      37             : #include "bgpd/bgp_attr.h"
      38             : #include "bgpd/bgp_label.h"
      39             : #include "bgpd/bgp_packet.h"
      40             : #include "bgpd/bgp_debug.h"
      41             : #include "bgpd/bgp_errors.h"
      42             : 
      43             : extern struct zclient *zclient;
      44             : 
      45           0 : int bgp_parse_fec_update(void)
      46             : {
      47           0 :         struct stream *s;
      48           0 :         struct bgp_dest *dest;
      49           0 :         struct bgp *bgp;
      50           0 :         struct bgp_table *table;
      51           0 :         struct prefix p;
      52           0 :         uint32_t label;
      53           0 :         afi_t afi;
      54           0 :         safi_t safi;
      55             : 
      56           0 :         s = zclient->ibuf;
      57             : 
      58           0 :         memset(&p, 0, sizeof(p));
      59           0 :         p.family = stream_getw(s);
      60           0 :         p.prefixlen = stream_getc(s);
      61           0 :         stream_get(p.u.val, s, PSIZE(p.prefixlen));
      62           0 :         label = stream_getl(s);
      63             : 
      64             :         /* hack for the bgp instance & SAFI = have to send/receive it */
      65           0 :         afi = family2afi(p.family);
      66           0 :         safi = SAFI_UNICAST;
      67           0 :         bgp = bgp_get_default();
      68           0 :         if (!bgp) {
      69           0 :                 zlog_debug("no default bgp instance");
      70           0 :                 return -1;
      71             :         }
      72             : 
      73           0 :         table = bgp->rib[afi][safi];
      74           0 :         if (!table) {
      75           0 :                 zlog_debug("no %u unicast table", p.family);
      76           0 :                 return -1;
      77             :         }
      78           0 :         dest = bgp_node_lookup(table, &p);
      79           0 :         if (!dest) {
      80           0 :                 zlog_debug("no node for the prefix");
      81           0 :                 return -1;
      82             :         }
      83             : 
      84             :         /* treat it as implicit withdraw - the label is invalid */
      85           0 :         if (label == MPLS_INVALID_LABEL)
      86           0 :                 bgp_unset_valid_label(&dest->local_label);
      87             :         else {
      88           0 :                 dest->local_label = mpls_lse_encode(label, 0, 0, 1);
      89           0 :                 bgp_set_valid_label(&dest->local_label);
      90             :         }
      91           0 :         SET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
      92           0 :         bgp_process(bgp, dest, afi, safi);
      93           0 :         bgp_dest_unlock_node(dest);
      94           0 :         return 1;
      95             : }
      96             : 
      97           0 : mpls_label_t bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi,
      98             :                            struct peer *to, afi_t afi, safi_t safi)
      99             : {
     100           0 :         struct peer *from;
     101           0 :         mpls_label_t remote_label;
     102           0 :         int reflect;
     103             : 
     104           0 :         if (!dest || !pi || !to)
     105             :                 return MPLS_INVALID_LABEL;
     106             : 
     107           0 :         remote_label = pi->extra ? pi->extra->label[0] : MPLS_INVALID_LABEL;
     108           0 :         from = pi->peer;
     109           0 :         reflect =
     110           0 :                 ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
     111             : 
     112           0 :         if (reflect
     113           0 :             && !CHECK_FLAG(to->af_flags[afi][safi],
     114             :                            PEER_FLAG_FORCE_NEXTHOP_SELF))
     115             :                 return remote_label;
     116             : 
     117           0 :         if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
     118             :                 return remote_label;
     119             : 
     120           0 :         return dest->local_label;
     121             : }
     122             : 
     123           0 : static void bgp_send_fec_register_label_msg(struct bgp_dest *dest, bool reg,
     124             :                                             uint32_t label_index)
     125             : {
     126           0 :         struct stream *s;
     127           0 :         int command;
     128           0 :         const struct prefix *p;
     129           0 :         uint16_t flags = 0;
     130           0 :         size_t flags_pos = 0;
     131           0 :         mpls_label_t *local_label = &(dest->local_label);
     132           0 :         uint32_t ttl = 0;
     133           0 :         uint32_t bos = 0;
     134           0 :         uint32_t exp = 0;
     135           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
     136           0 :         bool have_label_to_reg;
     137             : 
     138           0 :         mpls_lse_decode(*local_label, &label, &ttl, &exp, &bos);
     139             : 
     140           0 :         have_label_to_reg = bgp_is_valid_label(local_label) &&
     141             :                             label != MPLS_LABEL_IMPLICIT_NULL;
     142             : 
     143           0 :         p = bgp_dest_get_prefix(dest);
     144             : 
     145             :         /* Check socket. */
     146           0 :         if (!zclient || zclient->sock < 0)
     147           0 :                 return;
     148             : 
     149           0 :         if (BGP_DEBUG(labelpool, LABELPOOL))
     150           0 :                 zlog_debug("%s: FEC %sregister %pRN label_index=%u label=%u",
     151             :                            __func__, reg ? "" : "un", bgp_dest_to_rnode(dest),
     152             :                            label_index, label);
     153             :         /* If the route node has a local_label assigned or the
     154             :          * path node has an MPLS SR label index allowing zebra to
     155             :          * derive the label, proceed with registration. */
     156           0 :         s = zclient->obuf;
     157           0 :         stream_reset(s);
     158           0 :         command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
     159           0 :         zclient_create_header(s, command, VRF_DEFAULT);
     160           0 :         flags_pos = stream_get_endp(s); /* save position of 'flags' */
     161           0 :         stream_putw(s, flags);          /* initial flags */
     162           0 :         stream_putw(s, PREFIX_FAMILY(p));
     163           0 :         stream_put_prefix(s, p);
     164           0 :         if (reg) {
     165             :                 /* label index takes precedence over auto-assigned label. */
     166           0 :                 if (label_index != 0) {
     167           0 :                         flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
     168           0 :                         stream_putl(s, label_index);
     169           0 :                 } else if (have_label_to_reg) {
     170           0 :                         flags |= ZEBRA_FEC_REGISTER_LABEL;
     171           0 :                         stream_putl(s, label);
     172             :                 }
     173           0 :                 SET_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL);
     174             :         } else
     175           0 :                 UNSET_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL);
     176             : 
     177             :         /* Set length and flags */
     178           0 :         stream_putw_at(s, 0, stream_get_endp(s));
     179             : 
     180             :         /*
     181             :          * We only need to write new flags if this is a register
     182             :          */
     183           0 :         if (reg)
     184           0 :                 stream_putw_at(s, flags_pos, flags);
     185             : 
     186           0 :         zclient_send_message(zclient);
     187             : }
     188             : 
     189             : /**
     190             :  * This is passed as the callback function to bgp_labelpool.c:bgp_lp_get()
     191             :  * by bgp_reg_dereg_for_label() when a label needs to be obtained from
     192             :  * label pool.
     193             :  * Note that it will reject the allocated label if a label index is found,
     194             :  * because the label index supposes predictable labels
     195             :  */
     196           0 : int bgp_reg_for_label_callback(mpls_label_t new_label, void *labelid,
     197             :                                bool allocated)
     198             : {
     199           0 :         struct bgp_dest *dest;
     200             : 
     201           0 :         dest = labelid;
     202             : 
     203             :         /*
     204             :          * if the route had been removed or the request has gone then reject
     205             :          * the allocated label. The requesting code will have done what is
     206             :          * required to allocate the correct label
     207             :          */
     208           0 :         if (!CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
     209           0 :                 bgp_dest_unlock_node(dest);
     210           0 :                 return -1;
     211             :         }
     212             : 
     213           0 :         bgp_dest_unlock_node(dest);
     214             : 
     215           0 :         if (BGP_DEBUG(labelpool, LABELPOOL))
     216           0 :                 zlog_debug("%s: FEC %pRN label=%u, allocated=%d", __func__,
     217             :                            bgp_dest_to_rnode(dest), new_label, allocated);
     218             : 
     219           0 :         if (!allocated) {
     220             :                 /*
     221             :                  * previously-allocated label is now invalid, set to implicit
     222             :                  * null until new label arrives
     223             :                  */
     224           0 :                 if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
     225           0 :                         UNSET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
     226           0 :                         dest->local_label = mpls_lse_encode(
     227             :                                 MPLS_LABEL_IMPLICIT_NULL, 0, 0, 1);
     228           0 :                         bgp_set_valid_label(&dest->local_label);
     229             :                 }
     230             :         }
     231             : 
     232           0 :         dest->local_label = mpls_lse_encode(new_label, 0, 0, 1);
     233           0 :         bgp_set_valid_label(&dest->local_label);
     234             : 
     235             :         /*
     236             :          * Get back to registering the FEC
     237             :          */
     238           0 :         bgp_send_fec_register_label_msg(dest, true, 0);
     239             : 
     240           0 :         return 0;
     241             : }
     242             : 
     243           0 : void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi,
     244             :                              bool reg)
     245             : {
     246           0 :         bool with_label_index = false;
     247           0 :         const struct prefix *p;
     248           0 :         bool have_label_to_reg;
     249           0 :         uint32_t ttl = 0;
     250           0 :         uint32_t bos = 0;
     251           0 :         uint32_t exp = 0;
     252           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
     253             : 
     254           0 :         mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
     255             : 
     256           0 :         have_label_to_reg = bgp_is_valid_label(&dest->local_label) &&
     257             :                             label != MPLS_LABEL_IMPLICIT_NULL;
     258             : 
     259           0 :         p = bgp_dest_get_prefix(dest);
     260             : 
     261           0 :         if (BGP_DEBUG(labelpool, LABELPOOL))
     262           0 :                 zlog_debug("%s: %pFX: %s ", __func__, p,
     263             :                            (reg ? "reg" : "dereg"));
     264             : 
     265           0 :         if (reg) {
     266           0 :                 assert(pi);
     267             :                 /*
     268             :                  * Determine if we will let zebra should derive label from
     269             :                  * label index instead of bgpd requesting from label pool
     270             :                  */
     271           0 :                 if (CHECK_FLAG(pi->attr->flag,
     272             :                             ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID))
     273           0 :                         && pi->attr->label_index != BGP_INVALID_LABEL_INDEX) {
     274           0 :                         with_label_index = true;
     275           0 :                         UNSET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
     276             :                 } else {
     277             :                         /*
     278             :                          * If no label has been registered -- assume any label
     279             :                          * from label pool will do. This means that label index
     280             :                          * always takes precedence over auto-assigned labels.
     281             :                          */
     282           0 :                         if (!have_label_to_reg) {
     283           0 :                                 SET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
     284           0 :                                 if (BGP_DEBUG(labelpool, LABELPOOL))
     285           0 :                                         zlog_debug(
     286             :                                                 "%s: Requesting label from LP for %pFX",
     287             :                                                 __func__, p);
     288             :                                 /* bgp_reg_for_label_callback() will deal with
     289             :                                  * fec registration when it gets a label from
     290             :                                  * the pool. This means we'll never register
     291             :                                  * FECs withoutvalid labels.
     292             :                                  */
     293           0 :                                 bgp_lp_get(LP_TYPE_BGP_LU, dest,
     294             :                                            bgp_reg_for_label_callback);
     295           0 :                                 return;
     296             :                         }
     297             :                 }
     298             :         } else {
     299           0 :                 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
     300           0 :                 bgp_lp_release(LP_TYPE_BGP_LU, dest, label);
     301             :         }
     302             : 
     303           0 :         bgp_send_fec_register_label_msg(
     304             :                 dest, reg, with_label_index ? pi->attr->label_index : 0);
     305             : }
     306             : 
     307           0 : static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen,
     308             :                                mpls_label_t *label)
     309             : {
     310           0 :         uint8_t *data = pnt;
     311           0 :         uint8_t *lim = pnt + plen;
     312           0 :         uint8_t llen = 0;
     313           0 :         uint8_t label_depth = 0;
     314             : 
     315           0 :         for (; data < lim; data += BGP_LABEL_BYTES) {
     316           0 :                 memcpy(label, data, BGP_LABEL_BYTES);
     317           0 :                 llen += BGP_LABEL_BYTES;
     318             : 
     319           0 :                 bgp_set_valid_label(label);
     320           0 :                 label_depth += 1;
     321             : 
     322           0 :                 if (bgp_is_withdraw_label(label) || label_bos(label))
     323             :                         break;
     324             :         }
     325             : 
     326             :         /* If we RX multiple labels we will end up keeping only the last
     327             :          * one. We do not yet support a label stack greater than 1. */
     328           0 :         if (label_depth > 1)
     329           0 :                 zlog_info("%pBP rcvd UPDATE with label stack %d deep", peer,
     330             :                           label_depth);
     331             : 
     332           0 :         if (!(bgp_is_withdraw_label(label) || label_bos(label)))
     333           0 :                 flog_warn(
     334             :                         EC_BGP_INVALID_LABEL_STACK,
     335             :                         "%pBP rcvd UPDATE with invalid label stack - no bottom of stack",
     336             :                         peer);
     337             : 
     338           0 :         return llen;
     339             : }
     340             : 
     341           0 : int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
     342             :                          struct bgp_nlri *packet)
     343             : {
     344           0 :         uint8_t *pnt;
     345           0 :         uint8_t *lim;
     346           0 :         struct prefix p;
     347           0 :         int psize = 0;
     348           0 :         int prefixlen;
     349           0 :         afi_t afi;
     350           0 :         safi_t safi;
     351           0 :         bool addpath_capable;
     352           0 :         uint32_t addpath_id;
     353           0 :         mpls_label_t label = MPLS_INVALID_LABEL;
     354           0 :         uint8_t llen;
     355             : 
     356           0 :         pnt = packet->nlri;
     357           0 :         lim = pnt + packet->length;
     358           0 :         afi = packet->afi;
     359           0 :         safi = packet->safi;
     360           0 :         addpath_id = 0;
     361             : 
     362           0 :         addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
     363             : 
     364           0 :         for (; pnt < lim; pnt += psize) {
     365             :                 /* Clear prefix structure. */
     366           0 :                 memset(&p, 0, sizeof(p));
     367             : 
     368           0 :                 if (addpath_capable) {
     369             : 
     370             :                         /* When packet overflow occurs return immediately. */
     371           0 :                         if (pnt + BGP_ADDPATH_ID_LEN > lim)
     372             :                                 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
     373             : 
     374           0 :                         memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
     375           0 :                         addpath_id = ntohl(addpath_id);
     376           0 :                         pnt += BGP_ADDPATH_ID_LEN;
     377             :                 }
     378             : 
     379             :                 /* Fetch prefix length. */
     380           0 :                 prefixlen = *pnt++;
     381           0 :                 p.family = afi2family(packet->afi);
     382           0 :                 psize = PSIZE(prefixlen);
     383             : 
     384             :                 /* sanity check against packet data */
     385           0 :                 if ((pnt + psize) > lim) {
     386           0 :                         flog_err(
     387             :                                 EC_BGP_UPDATE_RCV,
     388             :                                 "%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
     389             :                                 peer->host, prefixlen, (uint)(lim - pnt));
     390           0 :                         return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
     391             :                 }
     392             : 
     393             :                 /* Fill in the labels */
     394           0 :                 llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
     395           0 :                 p.prefixlen = prefixlen - BSIZE(llen);
     396             : 
     397             :                 /* There needs to be at least one label */
     398           0 :                 if (prefixlen < 24) {
     399           0 :                         flog_err(EC_BGP_UPDATE_RCV,
     400             :                                  "%s [Error] Update packet error (wrong label length %d)",
     401             :                                  peer->host, prefixlen);
     402           0 :                         bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
     403             :                                         BGP_NOTIFY_UPDATE_INVAL_NETWORK);
     404           0 :                         return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH;
     405             :                 }
     406             : 
     407           0 :                 if ((afi == AFI_IP && p.prefixlen > IPV4_MAX_BITLEN)
     408           0 :                     || (afi == AFI_IP6 && p.prefixlen > IPV6_MAX_BITLEN))
     409             :                         return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
     410             : 
     411             :                 /* Fetch prefix from NLRI packet */
     412           0 :                 memcpy(&p.u.prefix, pnt + llen, psize - llen);
     413             : 
     414             :                 /* Check address. */
     415           0 :                 if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) {
     416           0 :                         if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
     417             :                                 /* From RFC4271 Section 6.3:
     418             :                                  *
     419             :                                  * If a prefix in the NLRI field is semantically
     420             :                                  * incorrect
     421             :                                  * (e.g., an unexpected multicast IP address),
     422             :                                  * an error SHOULD
     423             :                                  * be logged locally, and the prefix SHOULD be
     424             :                                  * ignored.
     425             :                                   */
     426           0 :                                 flog_err(
     427             :                                         EC_BGP_UPDATE_RCV,
     428             :                                         "%s: IPv4 labeled-unicast NLRI is multicast address %pI4, ignoring",
     429             :                                         peer->host, &p.u.prefix4);
     430           0 :                                 continue;
     431             :                         }
     432             :                 }
     433             : 
     434             :                 /* Check address. */
     435           0 :                 if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) {
     436           0 :                         if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
     437           0 :                                 flog_err(
     438             :                                         EC_BGP_UPDATE_RCV,
     439             :                                         "%s: IPv6 labeled-unicast NLRI is link-local address %pI6, ignoring",
     440             :                                         peer->host, &p.u.prefix6);
     441             : 
     442           0 :                                 continue;
     443             :                         }
     444             : 
     445           0 :                         if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
     446           0 :                                 flog_err(
     447             :                                         EC_BGP_UPDATE_RCV,
     448             :                                         "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
     449             :                                         peer->host, &p.u.prefix6);
     450             : 
     451           0 :                                 continue;
     452             :                         }
     453             :                 }
     454             : 
     455           0 :                 if (attr) {
     456           0 :                         bgp_update(peer, &p, addpath_id, attr, packet->afi,
     457             :                                    safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
     458             :                                    NULL, &label, 1, 0, NULL);
     459             :                 } else {
     460           0 :                         bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
     461             :                                      SAFI_UNICAST, ZEBRA_ROUTE_BGP,
     462             :                                      BGP_ROUTE_NORMAL, NULL, &label, 1, NULL);
     463             :                 }
     464             :         }
     465             : 
     466             :         /* Packet length consistency check. */
     467           0 :         if (pnt != lim) {
     468           0 :                 flog_err(
     469             :                         EC_BGP_UPDATE_RCV,
     470             :                         "%s [Error] Update packet error / L-U (%td data remaining after parsing)",
     471             :                         peer->host, lim - pnt);
     472           0 :                 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     473             :         }
     474             : 
     475             :         return BGP_NLRI_PARSE_OK;
     476             : }

Generated by: LCOV version v1.16-topotato