]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_attr.c
Merge pull request #12566 from Jafaral/lsa-op
[mirror_frr.git] / bgpd / bgp_attr.c
index b2d7bdcef4ed0af49c80c24f74ba9c9e9875ed4d..3d93e8a1acdadb0755ce245dfb70c7e9041b9bf1 100644 (file)
@@ -825,55 +825,56 @@ bool attrhash_cmp(const void *p1, const void *p2)
                && attr1->med == attr2->med
            && attr1->local_pref == attr2->local_pref
            && attr1->rmap_change_flags == attr2->rmap_change_flags) {
-               if (attr1->aggregator_as == attr2->aggregator_as
-                   && attr1->aggregator_addr.s_addr
-                              == attr2->aggregator_addr.s_addr
-                   && attr1->weight == attr2->weight
-                   && attr1->tag == attr2->tag
-                   && attr1->label_index == attr2->label_index
-                   && attr1->mp_nexthop_len == attr2->mp_nexthop_len
-                   && bgp_attr_get_ecommunity(attr1)
-                              == bgp_attr_get_ecommunity(attr2)
-                   && bgp_attr_get_ipv6_ecommunity(attr1)
-                              == bgp_attr_get_ipv6_ecommunity(attr2)
-                   && bgp_attr_get_lcommunity(attr1)
-                                  == bgp_attr_get_lcommunity(attr2)
-                   && bgp_attr_get_cluster(attr1)
-                              == bgp_attr_get_cluster(attr2)
-                   && bgp_attr_get_transit(attr1)
-                              == bgp_attr_get_transit(attr2)
-                   && bgp_attr_get_aigp_metric(attr1)
-                              == bgp_attr_get_aigp_metric(attr2)
-                   && attr1->rmap_table_id == attr2->rmap_table_id
-                   && (attr1->encap_tunneltype == attr2->encap_tunneltype)
-                   && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
+               if (attr1->aggregator_as == attr2->aggregator_as &&
+                   attr1->aggregator_addr.s_addr ==
+                           attr2->aggregator_addr.s_addr &&
+                   attr1->weight == attr2->weight &&
+                   attr1->tag == attr2->tag &&
+                   attr1->label_index == attr2->label_index &&
+                   attr1->mp_nexthop_len == attr2->mp_nexthop_len &&
+                   bgp_attr_get_ecommunity(attr1) ==
+                           bgp_attr_get_ecommunity(attr2) &&
+                   bgp_attr_get_ipv6_ecommunity(attr1) ==
+                           bgp_attr_get_ipv6_ecommunity(attr2) &&
+                   bgp_attr_get_lcommunity(attr1) ==
+                           bgp_attr_get_lcommunity(attr2) &&
+                   bgp_attr_get_cluster(attr1) ==
+                           bgp_attr_get_cluster(attr2) &&
+                   bgp_attr_get_transit(attr1) ==
+                           bgp_attr_get_transit(attr2) &&
+                   bgp_attr_get_aigp_metric(attr1) ==
+                           bgp_attr_get_aigp_metric(attr2) &&
+                   attr1->rmap_table_id == attr2->rmap_table_id &&
+                   (attr1->encap_tunneltype == attr2->encap_tunneltype) &&
+                   encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
 #ifdef ENABLE_BGP_VNC
                    && encap_same(bgp_attr_get_vnc_subtlvs(attr1),
                                  bgp_attr_get_vnc_subtlvs(attr2))
 #endif
                    && IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
-                                     &attr2->mp_nexthop_global)
-                   && IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
-                                     &attr2->mp_nexthop_local)
-                   && IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
-                                     &attr2->mp_nexthop_global_in)
-                   && IPV4_ADDR_SAME(&attr1->originator_id,
-                                     &attr2->originator_id)
-                   && overlay_index_same(attr1, attr2)
-                   && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t))
-                   && attr1->es_flags == attr2->es_flags
-                   && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum
-                   && attr1->df_pref == attr2->df_pref
-                   && attr1->df_alg == attr2->df_alg
-                   && attr1->nh_ifindex == attr2->nh_ifindex
-                   && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex
-                   && attr1->distance == attr2->distance
-                   && srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn)
-                   && srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn)
-                   && attr1->srte_color == attr2->srte_color
-                   && attr1->nh_type == attr2->nh_type
-                   && attr1->bh_type == attr2->bh_type
-                   && attr1->otc == attr2->otc)
+                                     &attr2->mp_nexthop_global) &&
+                   IPV6_ADDR_SAME(&attr1->mp_nexthop_local,
+                                  &attr2->mp_nexthop_local) &&
+                   IPV4_ADDR_SAME(&attr1->mp_nexthop_global_in,
+                                  &attr2->mp_nexthop_global_in) &&
+                   IPV4_ADDR_SAME(&attr1->originator_id,
+                                  &attr2->originator_id) &&
+                   overlay_index_same(attr1, attr2) &&
+                   !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) &&
+                   attr1->es_flags == attr2->es_flags &&
+                   attr1->mm_sync_seqnum == attr2->mm_sync_seqnum &&
+                   attr1->df_pref == attr2->df_pref &&
+                   attr1->df_alg == attr2->df_alg &&
+                   attr1->nh_ifindex == attr2->nh_ifindex &&
+                   attr1->nh_flag == attr2->nh_flag &&
+                   attr1->nh_lla_ifindex == attr2->nh_lla_ifindex &&
+                   attr1->distance == attr2->distance &&
+                   srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn) &&
+                   srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
+                   attr1->srte_color == attr2->srte_color &&
+                   attr1->nh_type == attr2->nh_type &&
+                   attr1->bh_type == attr2->bh_type &&
+                   attr1->otc == attr2->otc)
                        return true;
        }
 
@@ -904,20 +905,20 @@ static void attrhash_finish(void)
 static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty)
 {
        struct attr *attr = bucket->data;
-       char sid_str[BUFSIZ];
+       struct in6_addr *sid = NULL;
 
-       vty_out(vty, "attr[%ld] nexthop %pI4\n", attr->refcnt, &attr->nexthop);
-
-       sid_str[0] = '\0';
        if (attr->srv6_l3vpn)
-               inet_ntop(AF_INET6, &attr->srv6_l3vpn->sid, sid_str, BUFSIZ);
+               sid = &attr->srv6_l3vpn->sid;
        else if (attr->srv6_vpn)
-               inet_ntop(AF_INET6, &attr->srv6_vpn->sid, sid_str, BUFSIZ);
+               sid = &attr->srv6_vpn->sid;
+
+       vty_out(vty, "attr[%ld] nexthop %pI4\n", attr->refcnt, &attr->nexthop);
 
        vty_out(vty,
-               "\tflags: %" PRIu64" distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %s\n",
+               "\tflags: %" PRIu64
+               " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
                attr->flag, attr->distance, attr->med, attr->local_pref,
-               attr->origin, attr->weight, attr->label, sid_str);
+               attr->origin, attr->weight, attr->label, sid);
 }
 
 void attr_show_all(struct vty *vty)
@@ -1746,12 +1747,9 @@ enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
 
        if (ipv4_martian(&attr->nexthop) && !bgp->allow_martian) {
                uint8_t data[7]; /* type(2) + length(1) + nhop(4) */
-               char buf[INET_ADDRSTRLEN];
 
-               inet_ntop(AF_INET, &attr->nexthop.s_addr, buf,
-                         INET_ADDRSTRLEN);
-               flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s",
-                        buf);
+               flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %pI4",
+                        &attr->nexthop);
                data[0] = BGP_ATTR_FLAG_TRANS;
                data[1] = BGP_ATTR_NEXT_HOP;
                data[2] = BGP_ATTR_NHLEN_IPV4;
@@ -2257,6 +2255,12 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                                return BGP_ATTR_PARSE_WITHDRAW;
                        }
                        attr->nh_ifindex = peer->nexthop.ifp->ifindex;
+                       if (if_is_operative(peer->nexthop.ifp))
+                               SET_FLAG(attr->nh_flag,
+                                        BGP_ATTR_NH_IF_OPERSTATE);
+                       else
+                               UNSET_FLAG(attr->nh_flag,
+                                          BGP_ATTR_NH_IF_OPERSTATE);
                }
                break;
        case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
@@ -2274,6 +2278,12 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                                return BGP_ATTR_PARSE_WITHDRAW;
                        }
                        attr->nh_ifindex = peer->nexthop.ifp->ifindex;
+                       if (if_is_operative(peer->nexthop.ifp))
+                               SET_FLAG(attr->nh_flag,
+                                        BGP_ATTR_NH_IF_OPERSTATE);
+                       else
+                               UNSET_FLAG(attr->nh_flag,
+                                          BGP_ATTR_NH_IF_OPERSTATE);
                }
                if (attr->mp_nexthop_len
                    == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
@@ -2709,6 +2719,18 @@ bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
        }
 
        if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
+               if (STREAM_READABLE(peer->curr) <
+                   BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
+                       flog_err(
+                               EC_BGP_ATTR_LEN,
+                               "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %zu remaining in UPDATE)",
+                               BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
+                               STREAM_READABLE(peer->curr));
+                       return bgp_attr_malformed(
+                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                               args->total);
+               }
+
                loc_block_len = stream_getc(peer->curr);
                loc_node_len = stream_getc(peer->curr);
                func_len = stream_getc(peer->curr);
@@ -2758,7 +2780,6 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
        uint16_t length, endpoint_behavior;
        size_t headersz = sizeof(type) + sizeof(length);
        enum bgp_attr_parse_ret err;
-       char buf[BUFSIZ];
 
        if (STREAM_READABLE(peer->curr) < headersz) {
                flog_err(
@@ -2782,6 +2803,17 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
        }
 
        if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO) {
+               if (STREAM_READABLE(peer->curr) <
+                   BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH) {
+                       flog_err(
+                               EC_BGP_ATTR_LEN,
+                               "Malformed SRv6 Service Sub-TLV attribute - insufficent data (need %d for attribute data, have %zu remaining in UPDATE)",
+                               BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_INFO_LENGTH,
+                               STREAM_READABLE(peer->curr));
+                       return bgp_attr_malformed(
+                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                               args->total);
+               }
                stream_getc(peer->curr);
                stream_get(&ipv6_sid, peer->curr, sizeof(ipv6_sid));
                sid_flags = stream_getc(peer->curr);
@@ -2789,12 +2821,11 @@ bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
                stream_getc(peer->curr);
 
                /* Log SRv6 Service Sub-TLV */
-               if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
-                       inet_ntop(AF_INET6, &ipv6_sid, buf, sizeof(buf));
+               if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
                        zlog_debug(
-                               "%s: srv6-l3-srv sid %s, sid-flags 0x%02x, end-behaviour 0x%04x",
-                               __func__, buf, sid_flags, endpoint_behavior);
-               }
+                               "%s: srv6-l3-srv sid %pI6, sid-flags 0x%02x, end-behaviour 0x%04x",
+                               __func__, &ipv6_sid, sid_flags,
+                               endpoint_behavior);
 
                /* Configure from Info */
                if (attr->srv6_l3vpn) {
@@ -2855,7 +2886,6 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
        uint32_t srgb_range;
        int srgb_count;
        uint8_t sid_type, sid_flags;
-       char buf[BUFSIZ];
 
        if (type == BGP_PREFIX_SID_LABEL_INDEX) {
                if (STREAM_READABLE(peer->curr) < length
@@ -2986,12 +3016,10 @@ bgp_attr_psid_sub(uint8_t type, uint16_t length,
                           sizeof(ipv6_sid)); /* sid_value */
 
                /* Log VPN-SID Sub-TLV */
-               if (BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
-                       inet_ntop(AF_INET6, &ipv6_sid, buf, sizeof(buf));
+               if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
                        zlog_debug(
-                               "%s: vpn-sid: sid %s, sid-type 0x%02x sid-flags 0x%02x",
-                               __func__, buf, sid_type, sid_flags);
-               }
+                               "%s: vpn-sid: sid %pI6, sid-type 0x%02x sid-flags 0x%02x",
+                               __func__, &ipv6_sid, sid_type, sid_flags);
 
                /* Configure from Info */
                if (attr->srv6_vpn) {
@@ -3861,7 +3889,10 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
                                stream_putc(s, attr->mp_nexthop_len);
                                stream_put_ipv4(s, attr->nexthop.s_addr);
                        }
-               default:
+                       break;
+               case SAFI_UNSPEC:
+               case SAFI_MAX:
+                       assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
                        break;
                }
                break;
@@ -3912,17 +3943,24 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
                        break;
                case SAFI_FLOWSPEC:
                        stream_putc(s, 0); /* no nexthop for flowspec */
-               default:
+                       break;
+               case SAFI_UNSPEC:
+               case SAFI_MAX:
+                       assert(!"SAFI's UNSPEC or MAX being specified are a DEV ESCAPE");
                        break;
                }
                break;
-       default:
+       case AFI_L2VPN:
                if (safi != SAFI_FLOWSPEC)
                        flog_err(
                                EC_BGP_ATTR_NH_SEND_LEN,
                                "Bad nexthop when sending to %s, AFI %u SAFI %u nhlen %d",
                                peer->host, afi, safi, attr->mp_nexthop_len);
                break;
+       case AFI_UNSPEC:
+       case AFI_MAX:
+               assert(!"DEV ESCAPE: AFI_UNSPEC or AFI_MAX should not be used here");
+               break;
        }
 
        /* SNPA */
@@ -3936,7 +3974,12 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
                              uint32_t num_labels, bool addpath_capable,
                              uint32_t addpath_tx_id, struct attr *attr)
 {
-       if (safi == SAFI_MPLS_VPN) {
+       switch (safi) {
+       case SAFI_UNSPEC:
+       case SAFI_MAX:
+               assert(!"Dev escape usage of SAFI_UNSPEC or MAX");
+               break;
+       case SAFI_MPLS_VPN:
                if (addpath_capable)
                        stream_putl(s, addpath_tx_id);
                /* Label, RD, Prefix write. */
@@ -3944,33 +3987,74 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
                stream_put(s, label, BGP_LABEL_BYTES);
                stream_put(s, prd->val, 8);
                stream_put(s, &p->u.prefix, PSIZE(p->prefixlen));
-       } else if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
-               /* EVPN prefix - contents depend on type */
-               bgp_evpn_encode_prefix(s, p, prd, label, num_labels, attr,
-                                      addpath_capable, addpath_tx_id);
-       } else if (safi == SAFI_LABELED_UNICAST) {
+               break;
+       case SAFI_EVPN:
+               if (afi == AFI_L2VPN)
+                       /* EVPN prefix - contents depend on type */
+                       bgp_evpn_encode_prefix(s, p, prd, label, num_labels,
+                                              attr, addpath_capable,
+                                              addpath_tx_id);
+               else
+                       assert(!"Add encoding bits here for other AFI's");
+               break;
+       case SAFI_LABELED_UNICAST:
                /* Prefix write with label. */
                stream_put_labeled_prefix(s, p, label, addpath_capable,
                                          addpath_tx_id);
-       } else if (safi == SAFI_FLOWSPEC) {
+               break;
+       case SAFI_FLOWSPEC:
                stream_putc(s, p->u.prefix_flowspec.prefixlen);
                stream_put(s, (const void *)p->u.prefix_flowspec.ptr,
                           p->u.prefix_flowspec.prefixlen);
-       } else
+               break;
+
+       case SAFI_UNICAST:
+       case SAFI_MULTICAST:
                stream_put_prefix_addpath(s, p, addpath_capable, addpath_tx_id);
+               break;
+       case SAFI_ENCAP:
+               assert(!"Please add proper encoding of SAFI_ENCAP");
+               break;
+       }
 }
 
 size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
                                     const struct prefix *p)
 {
        int size = PSIZE(p->prefixlen);
-       if (safi == SAFI_MPLS_VPN)
+
+       switch (safi) {
+       case SAFI_UNSPEC:
+       case SAFI_MAX:
+               assert(!"Attempting to figure size for a SAFI_UNSPEC/SAFI_MAX this is a DEV ESCAPE");
+               break;
+       case SAFI_UNICAST:
+       case SAFI_MULTICAST:
+               break;
+       case SAFI_MPLS_VPN:
                size += 88;
-       else if (safi == SAFI_LABELED_UNICAST)
+               break;
+       case SAFI_ENCAP:
+               /* This has to be wrong, but I don't know what to put here */
+               assert(!"Do we try to use this?");
+               break;
+       case SAFI_LABELED_UNICAST:
                size += BGP_LABEL_BYTES;
-       else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
-               size += 232; // TODO: Maximum possible for type-2, type-3 and
-                            // type-5
+               break;
+       case SAFI_EVPN:
+               /*
+                * TODO: Maximum possible for type-2, type-3 and type-5
+                */
+               if (afi == AFI_L2VPN)
+                       size += 232;
+               else
+                       assert(!"Attempting to figure size for SAFI_EVPN and !AFI_L2VPN and FRR will not have the proper values");
+               break;
+       case SAFI_FLOWSPEC:
+               size = ((struct prefix_fs *)p)->prefix.prefixlen;
+               break;
+       }
+
        return size;
 }
 
@@ -4506,7 +4590,9 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
                        stream_put(s, &attr->srv6_l3vpn->sid,
                                   sizeof(attr->srv6_l3vpn->sid)); /* sid */
                        stream_putc(s, 0);      /* sid_flags */
-                       stream_putw(s, 0xffff); /* endpoint */
+                       stream_putw(s,
+                                   attr->srv6_l3vpn
+                                           ->endpoint_behavior); /* endpoint */
                        stream_putc(s, 0);      /* reserved */
                        stream_putc(
                                s,
@@ -4609,7 +4695,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
        }
 
        /* AIGP */
-       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
+       if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
            (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
             peer->sort != BGP_PEER_EBGP)) {
                /* At the moment only AIGP Metric TLV exists for AIGP