]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
bgp: structs refactoring - BGP_ROUTE_ATTRIBUTES and BGP_PROTO_ATTRIBUTES created
authorKaterina Kubecova <katerina.kubecova@nic.cz>
Mon, 16 Jun 2025 13:26:56 +0000 (15:26 +0200)
committerKaterina Kubecova <katerina.kubecova@nic.cz>
Thu, 19 Jun 2025 15:00:39 +0000 (17:00 +0200)
nest/route.h
proto/bgp/attrs.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c
proto/mrt/mrt.c
proto/mrt/mrt_load.c
proto/mrt/mrt_load.h
proto/mrt/mrtload.Y
sysdep/unix/io.c

index 5a9e7fa16fdb6be123d7711b3c9b4cc0f86ca3f5..41940fb922b619597cd8b654789acef7984dac8e 100644 (file)
@@ -561,6 +561,7 @@ const char *ea_custom_name(uint ea);
 #define EAF_TYPE_STRING 0x16           /* Text string */
 #define EAF_EMBEDDED 0x01              /* Data stored in eattr.u.data (part of type spec) */
 #define EAF_VAR_LENGTH 0x02            /* Attribute length is variable (part of type spec) */
+#define EAF_PROTO_ATTR_PTR 0x18 /* Pointer to bgp_proto_attributes */
 
 typedef struct adata {
   uint length;                         /* Length of data */
index 489405134996f1afe1133cf482b6cc0325cc5e71..52c54ef2e2c50d0a415fdbfa4a5556020429094e 100644 (file)
@@ -450,7 +450,8 @@ bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte
 {
   int as_length = s->as4_session ? 4 : 2;
   int as_sets = s->allow_as_sets;
-  int as_confed = s->confederation && s->is_interior;
+  struct bgp_proto_attributes *proto_attrs = s->proto_attrs;
+  int as_confed = proto_attrs->confederation && proto_attrs->is_interior;
   char err[128];
 
   if (!as_path_valid(data, len, as_length, as_sets, as_confed, err, sizeof(err)))
@@ -465,13 +466,13 @@ bgp_decode_as_path(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte
   }
 
   /* In some circumstances check for initial AS_CONFED_SEQUENCE; RFC 5065 5.0 */
-  if (s->is_interior && !s->is_internal &&
+  if (proto_attrs->is_interior && !proto_attrs->is_internal &&
       ((len < 2) || (data[0] != AS_PATH_CONFED_SEQUENCE)))
     WITHDRAW("Malformed AS_PATH attribute - %s", "missing initial AS_CONFED_SEQUENCE");
 
   /* Reject routes with first AS in AS_PATH not matching neighbor AS; RFC 4271 6.3 */
-  if (!s->is_internal && s->enforce_first_as &&
-      !bgp_as_path_first_as_equal(data, len, s->remote_as))
+  if (!proto_attrs->is_internal && s->enforce_first_as &&
+      !bgp_as_path_first_as_equal(data, len, proto_attrs->remote_as))
     WITHDRAW("Malformed AS_PATH attribute - %s", "First AS differs from neigbor AS");
 
   bgp_set_attr_data(to, s->pool, BA_AS_PATH, flags, data, len);
@@ -560,7 +561,7 @@ bgp_export_local_pref(struct bgp_export_state *s, eattr *a)
 static void
 bgp_decode_local_pref(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
 {
-  if (!s->is_interior && !s->allow_local_pref)
+  if (!s->proto_attrs->is_interior && !s->allow_local_pref)
     DISCARD(BAD_EBGP, "LOCAL_PREF");
 
   if (len != 4)
@@ -654,7 +655,7 @@ bgp_export_originator_id(struct bgp_export_state *s, eattr *a)
 static void
 bgp_decode_originator_id(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
 {
-  if (!s->is_internal)
+  if (!s->proto_attrs->is_internal)
     DISCARD(BAD_EBGP, "ORIGINATOR_ID");
 
   if (len != 4)
@@ -678,7 +679,7 @@ bgp_export_cluster_list(struct bgp_export_state *s UNUSED, eattr *a)
 static void
 bgp_decode_cluster_list(struct bgp_parse_state *s, uint code UNUSED, uint flags, byte *data, uint len, ea_list **to)
 {
-  if (!s->is_internal)
+  if (!s->proto_attrs->is_internal)
     DISCARD(BAD_EBGP, "CLUSTER_LIST");
 
   if (!len || (len % 4))
@@ -958,6 +959,18 @@ bgp_encode_mpls_label_stack(struct bgp_write_state *s, eattr *a, byte *buf UNUSE
   return 0;
 }
 
+static int
+bgp_encode_proto_attrs(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte *buf UNUSED, uint size UNUSED)
+{
+  return 0;
+}
+
+static void
+bgp_decode_proto_attrs(struct bgp_parse_state *s UNUSED, uint code UNUSED, uint flags UNUSED, byte *data UNUSED, uint len UNUSED, ea_list **to UNUSED)
+{
+  return;
+}
+
 static void
 bgp_decode_mpls_label_stack(struct bgp_parse_state *s, uint code UNUSED, uint flags UNUSED, byte *data UNUSED, uint len UNUSED, ea_list **to UNUSED)
 {
@@ -1138,6 +1151,13 @@ static const struct bgp_attr_desc bgp_attr_table[] = {
     .encode = bgp_encode_u32,
     .decode = bgp_decode_otc,
   },
+  [BA_PROTO_ATTRS] = {
+    .name = "bgp proto attrs",
+    .type = EAF_PROTO_ATTR_PTR,
+    .flags = BAF_OPERATIONAL,
+    .encode = bgp_encode_proto_attrs,
+    .decode = bgp_decode_proto_attrs,
+  },
   [BA_MPLS_LABEL_STACK] = {
     .name = "mpls_label_stack",
     .type = EAF_TYPE_INT_SET,
@@ -1314,7 +1334,7 @@ static inline int
 bgp_originator_id_loopy(struct bgp_parse_state *s, ea_list *attrs)
 {
   eattr *e = bgp_find_attr(attrs, BA_ORIGINATOR_ID);
-  return (e && (e->u.data == s->local_id));
+  return (e && (e->u.data == s->proto_attrs->local_id));
 }
 
 static inline int
@@ -1437,24 +1457,24 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
 #define IS_LOOP(msg, args...)  { RTRACE("update is loop (" msg "), treating as withdraw", ##args); goto loop; }
 
   /* Reject routes with our ASN in AS_PATH attribute */
-  if (bgp_as_path_loopy(s, attrs, s->local_as))
+  if (bgp_as_path_loopy(s, attrs, s->proto_attrs->local_as))
     goto loop;
 
   /* Reject routes with our Confederation ID in AS_PATH attribute; RFC 5065 4.0 */
-  if ((s->public_as != s->local_as) && bgp_as_path_loopy(s, attrs, s->public_as))
+  if ((s->public_as != s->proto_attrs->local_as) && bgp_as_path_loopy(s, attrs, s->public_as))
     goto loop;
 
   /* Reject routes with our Router ID in ORIGINATOR_ID attribute; RFC 4456 8 */
-  if (s->is_internal && bgp_originator_id_loopy(s, attrs))
+  if (s->proto_attrs->is_internal && bgp_originator_id_loopy(s, attrs))
     goto loop;
 
   /* Reject routes with our Cluster ID in CLUSTER_LIST attribute; RFC 4456 8 */
-  if (s->rr_client && bgp_cluster_list_loopy(s->rr_cluster_id, attrs))
+  if (s->rr_client && bgp_cluster_list_loopy(s->proto_attrs->rr_cluster_id, attrs))
     goto loop;
 
   /* If there is no local preference, define one */
   if (!BIT32_TEST(s->attrs_seen, BA_LOCAL_PREF))
-    bgp_set_attr_u32(&attrs, s->pool, BA_LOCAL_PREF, 0, s->default_local_pref);
+    bgp_set_attr_u32(&attrs, s->pool, BA_LOCAL_PREF, 0, s->proto_attrs->default_local_pref);
 
   return attrs;
 
@@ -1499,7 +1519,7 @@ bgp_finish_attrs(struct bgp_parse_state *s, rta *a)
       WITHDRAW("Route leak detected - OTC attribute from downstream");
 
     /* Reject routes from peers if they are leaked */
-    if (e && (s->local_role == BGP_ROLE_PEER) && (e->u.data != s->remote_as))
+    if (e && (s->local_role == BGP_ROLE_PEER) && (e->u.data != s->proto_attrs->remote_as))
       WITHDRAW("Route leak detected - OTC attribute with mismatched ASN (%u)",
               (uint) e->u.data);
 
@@ -1507,7 +1527,7 @@ bgp_finish_attrs(struct bgp_parse_state *s, rta *a)
     if (!e && (s->local_role == BGP_ROLE_CUSTOMER ||
               s->local_role == BGP_ROLE_PEER ||
               s->local_role == BGP_ROLE_RS_CLIENT))
-      bgp_set_attr_u32(&a->eattrs, s->pool, BA_ONLY_TO_CUSTOMER, 0, s->remote_as);
+      bgp_set_attr_u32(&a->eattrs, s->pool, BA_ONLY_TO_CUSTOMER, 0, s->proto_attrs->remote_as);
   }
 
   /* Apply MPLS policy for labeled SAFIs */
@@ -1987,8 +2007,8 @@ bgp_get_neighbor(rte *r)
     return as;
 
   /* If AS_PATH is not defined, we treat rte as locally originated */
-  struct bgp_proto *p = (void *) r->src->proto;
-  return p->cf->confederation ?: p->local_as;
+  struct bgp_proto_attributes *p = (struct bgp_proto_attributes *) ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr;
+  return p->confederation ?: p->local_as;
 }
 
 static inline int
@@ -2017,8 +2037,8 @@ rte_stale(rte *r)
 int
 bgp_rte_better(rte *new, rte *old)
 {
-  struct bgp_proto *new_bgp = (struct bgp_proto *) new->src->proto;
-  struct bgp_proto *old_bgp = (struct bgp_proto *) old->src->proto;
+  struct bgp_proto_attributes *new_bgp = (struct bgp_proto_attributes *) ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr;
+  struct bgp_proto_attributes *old_bgp = (struct bgp_proto_attributes *) ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr;
   eattr *x, *y;
   u32 n, o;
 
@@ -2049,8 +2069,8 @@ bgp_rte_better(rte *new, rte *old)
  /* Start with local preferences */
   x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
   y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
-  n = x ? x->u.data : new_bgp->cf->default_local_pref;
-  o = y ? y->u.data : old_bgp->cf->default_local_pref;
+  n = x ? x->u.data : new_bgp->default_local_pref;
+  o = y ? y->u.data : old_bgp->default_local_pref;
   if (n > o)
     return 1;
   if (n < o)
@@ -2065,7 +2085,7 @@ bgp_rte_better(rte *new, rte *old)
     return 0;
 
   /* RFC 4271 9.1.2.2. a)  Use AS path lengths */
-  if (new_bgp->cf->compare_path_lengths || old_bgp->cf->compare_path_lengths)
+  if (new_bgp->compare_path_lengths || old_bgp->compare_path_lengths)
   {
     x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
     y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
@@ -2098,13 +2118,13 @@ bgp_rte_better(rte *new, rte *old)
    * same behavior as used by default in Cisco routers, so it is
    * probably not a big issue.
    */
-  if (new_bgp->cf->med_metric || old_bgp->cf->med_metric ||
+  if (new_bgp->med_metric || old_bgp->med_metric ||
       (bgp_get_neighbor(new) == bgp_get_neighbor(old)))
   {
     x = ea_find(new->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
     y = ea_find(old->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
-    n = x ? x->u.data : new_bgp->cf->default_med;
-    o = y ? y->u.data : old_bgp->cf->default_med;
+    n = x ? x->u.data : new_bgp->default_med;
+    o = y ? y->u.data : old_bgp->default_med;
     if (n < o)
       return 1;
     if (n > o)
@@ -2118,8 +2138,8 @@ bgp_rte_better(rte *new, rte *old)
     return 1;
 
   /* RFC 4271 9.1.2.2. e) Compare IGP metrics */
-  n = new_bgp->cf->igp_metric ? new->attrs->igp_metric : 0;
-  o = old_bgp->cf->igp_metric ? old->attrs->igp_metric : 0;
+  n = new_bgp->igp_metric ? new->attrs->igp_metric : 0;
+  o = old_bgp->igp_metric ? old->attrs->igp_metric : 0;
   if (n < o)
     return 1;
   if (n > o)
@@ -2134,7 +2154,7 @@ bgp_rte_better(rte *new, rte *old)
 
   /* RFC 5004 - prefer older routes */
   /* (if both are external and from different peer) */
-  if ((new_bgp->cf->prefer_older || old_bgp->cf->prefer_older) &&
+  if ((new_bgp->prefer_older || old_bgp->prefer_older) &&
       !new_bgp->is_internal && n != o)
     return 0;
 
@@ -2162,8 +2182,8 @@ bgp_rte_better(rte *new, rte *old)
 int
 bgp_rte_mergable(rte *pri, rte *sec)
 {
-  struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->src->proto;
-  struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->src->proto;
+  struct bgp_proto_attributes *pri_bgp = (struct bgp_proto_attributes *) ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr;
+  struct bgp_proto_attributes *sec_bgp = (struct bgp_proto_attributes *) ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr;
   eattr *x, *y;
   u32 p, s;
 
@@ -2182,13 +2202,13 @@ bgp_rte_mergable(rte *pri, rte *sec)
   /* Start with local preferences */
   x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
   y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
-  p = x ? x->u.data : pri_bgp->cf->default_local_pref;
-  s = y ? y->u.data : sec_bgp->cf->default_local_pref;
+  p = x ? x->u.data : pri_bgp->default_local_pref;
+  s = y ? y->u.data : sec_bgp->default_local_pref;
   if (p != s)
     return 0;
 
   /* RFC 4271 9.1.2.2. a)  Use AS path lengths */
-  if (pri_bgp->cf->compare_path_lengths || sec_bgp->cf->compare_path_lengths)
+  if (pri_bgp->compare_path_lengths || sec_bgp->compare_path_lengths)
   {
     x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
     y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
@@ -2211,13 +2231,13 @@ bgp_rte_mergable(rte *pri, rte *sec)
     return 0;
 
   /* RFC 4271 9.1.2.2. c) Compare MED's */
-  if (pri_bgp->cf->med_metric || sec_bgp->cf->med_metric ||
+  if (pri_bgp->med_metric || sec_bgp->med_metric ||
       (bgp_get_neighbor(pri) == bgp_get_neighbor(sec)))
   {
     x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
     y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_MULTI_EXIT_DISC));
-    p = x ? x->u.data : pri_bgp->cf->default_med;
-    s = y ? y->u.data : sec_bgp->cf->default_med;
+    p = x ? x->u.data : pri_bgp->default_med;
+    s = y ? y->u.data : sec_bgp->default_med;
     if (p != s)
       return 0;
   }
@@ -2227,8 +2247,8 @@ bgp_rte_mergable(rte *pri, rte *sec)
     return 0;
 
   /* RFC 4271 9.1.2.2. e) Compare IGP metrics */
-  p = pri_bgp->cf->igp_metric ? pri->attrs->igp_metric : 0;
-  s = sec_bgp->cf->igp_metric ? sec->attrs->igp_metric : 0;
+  p = pri_bgp->igp_metric ? pri->attrs->igp_metric : 0;
+  s = sec_bgp->igp_metric ? sec->attrs->igp_metric : 0;
   if (p != s)
     return 0;
 
@@ -2247,8 +2267,8 @@ same_group(rte *r, u32 lpref, u32 lasn)
 static inline int
 use_deterministic_med(rte *r)
 {
-  struct proto *P = r->src->proto;
-  return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med;
+  struct bgp_proto_attributes *pa = (struct bgp_proto_attributes *) ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_PROTO_ATTRS))->u.ptr;
+  return (pa->routes_proto == BGP_ROUTE) && pa->deterministic_med;
 }
 
 int
index 1f3ae87ca3a32d9687a0fe6ab29fda30a40e2d16..84c273f410e167c7580df72052c3138aac43d7b2 100644 (file)
@@ -2064,6 +2064,14 @@ bgp_start(struct proto *P)
   p->remote_as = cf->remote_as;
   p->public_as = cf->local_as;
 
+  p->deterministic_med = cf->deterministic_med;
+  p->default_local_pref = cf->default_local_pref;
+  p->compare_path_lengths = cf->compare_path_lengths;
+  p->confederation = cf->confederation;
+  p->med_metric = cf->med_metric;
+  p->default_med = cf->default_med;
+  p->igp_metric = cf->igp_metric;
+  p->prefer_older = cf->prefer_older;
   /* For dynamic BGP childs, remote_ip is already set */
   if (ipa_nonzero(cf->remote_ip))
     p->remote_ip = cf->remote_ip;
@@ -2251,6 +2259,7 @@ bgp_init(struct proto_config *CF)
   P->rte_igp_metric = bgp_rte_igp_metric;
 
   p->cf = cf;
+  p->routes_proto = BGP_ROUTE;
   p->is_internal = (cf->local_as == cf->remote_as);
   p->is_interior = p->is_internal || cf->confederation_member;
   p->rs_client = cf->rs_client;
@@ -2744,6 +2753,19 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
        || (old->remote_range && new->remote_range && net_equal(old->remote_range, new->remote_range)))
     && !bstrcmp(old->dynamic_name, new->dynamic_name)
     && (old->dynamic_name_digits == new->dynamic_name_digits);
+    /* Options influencing best route selection; for now, restarting, in future
+   * we should just recalculate the tables */
+  same = same && p->deterministic_med == new->deterministic_med
+              && p->compare_path_lengths == new->compare_path_lengths
+              && p->med_metric == new->med_metric
+              && p->default_med == new->default_med
+              && p->igp_metric == new->igp_metric
+              && p->prefer_older == new->prefer_older;
+
+  /* looks like this does not affect best route selection */
+  p->default_local_pref = new->default_local_pref;
+  p->confederation = new->confederation;
 
   /* Reconfigure TCP-AP */
   same = same && bgp_reconfigure_ao_keys(p, new);
index adc1e83594025f846e735b9d7fbf38a087b2c1b7..14f9f8f3be846389032da332fb09490c1f8c7c79 100644 (file)
@@ -74,8 +74,24 @@ struct bgp_af_desc {
 };
 
 
+#define BGP_ROUTE_ATTRIBUTES \
+  int deterministic_med;               /* Use more complicated algo to have strict RFC 4271 MED comparison */ \
+  u32 default_local_pref;              /* Default value for LOCAL_PREF attribute */ \
+  int compare_path_lengths;            /* Use path lengths when selecting best route */ \
+  u32 confederation;                   /* Confederation ID, or zero if confeds not active */ \
+  int med_metric;                      /* Compare MULTI_EXIT_DISC even between routes from differen ASes */ \
+  u32 default_med;                     /* Default value for MULTI_EXIT_DISC attribute */ \
+  int igp_metric;                      /* Use IGP metrics when selecting best route */ \
+  int prefer_older;                    /* Prefer older routes according to RFC 5004 */ \
+
+struct rte_class_config { BGP_ROUTE_ATTRIBUTES };
+
 struct bgp_config {
   struct proto_config c;
+  union {
+    struct rte_class_config rte_class;
+    struct { BGP_ROUTE_ATTRIBUTES; };
+  };
   u32 local_as, remote_as;
   ip_addr local_ip;                    /* Source address to use */
   ip_addr remote_ip;
@@ -87,13 +103,6 @@ struct bgp_config {
   int strict_bind;                     /* Bind listening socket to local address */
   int free_bind;                       /* Bind listening socket with SKF_FREEBIND */
   int ttl_security;                    /* Enable TTL security [RFC 5082] */
-  int compare_path_lengths;            /* Use path lengths when selecting best route */
-  int med_metric;                      /* Compare MULTI_EXIT_DISC even between routes from differen ASes */
-  int igp_metric;                      /* Use IGP metrics when selecting best route */
-  int prefer_older;                    /* Prefer older routes according to RFC 5004 */
-  int deterministic_med;               /* Use more complicated algo to have strict RFC 4271 MED comparison */
-  u32 default_local_pref;              /* Default value for LOCAL_PREF attribute */
-  u32 default_med;                     /* Default value for MULTI_EXIT_DISC attribute */
   int capabilities;                    /* Enable capability handshake [RFC 5492] */
   int enable_refresh;                  /* Enable local support for route refresh [RFC 2918] */
   int enable_enhanced_refresh;         /* Enable local support for enhanced route refresh [RFC 7313] */
@@ -103,7 +112,6 @@ struct bgp_config {
   u32 rr_cluster_id;                   /* Route reflector cluster ID, if different from local ID */
   int rr_client;                       /* Whether neighbor is RR client of me */
   int rs_client;                       /* Whether neighbor is RS client of me */
-  u32 confederation;                   /* Confederation ID, or zero if confeds not active */
   int confederation_member;            /* Whether neighbor AS is member of our confederation */
   int passive;                         /* Do not initiate outgoing connection */
   int interpret_communities;           /* Hardwired handling of well-known communities */
@@ -351,22 +359,38 @@ struct bgp_conn {
   uint hold_time, keepalive_time, send_hold_time;      /* Times calculated from my and neighbor's requirements */
 };
 
+enum route_proto {
+  BGP_ROUTE = 1,
+};
+
+#define BGP_PROTO_ATTRIBUTES \
+  enum route_proto routes_proto; /* protocol enum (pointer to bgp_proto_attributes is given to route eattrs) */ \
+  u32 local_as, remote_as; \
+  ip_addr local_ip, remote_ip; \
+  u32 local_id;                                /* BGP identifier of this router */ \
+  u32 remote_id;               /* BGP identifier of the neighbor */ \
+  u32 rr_cluster_id;   /* Route reflector cluster ID */ \
+  u8 rr_client;       /* Whether neighbor is RR client of me */ \
+  u8 rs_client;                                /* Whether neighbor is RS client of me */ \
+  u8 is_internal;                      /* Internal BGP session (local_as == remote_as) */ \
+  u8 is_interior;                      /* Internal or intra-confederation BGP session */ \
+  \
+  /* from conf */ \
+  BGP_ROUTE_ATTRIBUTES\
+
+struct bgp_proto_attributes { BGP_PROTO_ATTRIBUTES };
+
 struct bgp_proto {
   struct proto p;
   const struct bgp_config *cf;         /* Shortcut to BGP configuration */
   const char *hostname;      /* Hostname for this BGP protocol */
-  ip_addr local_ip, remote_ip;
-  u32 local_as, remote_as;
+  union {
+    struct bgp_proto_attributes proto_attrs;
+    struct { BGP_PROTO_ATTRIBUTES; };
+  };
   u32 public_as;                       /* Externally visible ASN (local_as or confederation id) */
-  u32 local_id;                                /* BGP identifier of this router */
-  u32 remote_id;                       /* BGP identifier of the neighbor */
-  u32 rr_cluster_id;                   /* Route reflector cluster ID */
   u8 start_state;                      /* Substates that partitions BS_START */
-  u8 is_internal;                      /* Internal BGP session (local_as == remote_as) */
-  u8 is_interior;                      /* Internal or intra-confederation BGP session */
   u8 as4_session;                      /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
-  u8 rr_client;                                /* Whether neighbor is RR client of me */
-  u8 rs_client;                                /* Whether neighbor is RS client of me */
   u8 ipv4;                             /* Use IPv4 connection, i.e. remote_ip is IPv4 */
   u8 passive;                          /* Do not initiate outgoing connection */
   u8 route_refresh;                    /* Route refresh allowed to send [RFC 2918] */
@@ -494,15 +518,10 @@ struct bgp_write_state {
 
 struct bgp_parse_state {
   // instead of struct bgp_proto *proto;
+  struct bgp_proto_attributes *proto_attrs;
   struct proto *p;
-  u32 local_as;
   u32 public_as;
-  u32 remote_as;
-  u32 rr_cluster_id;
-  u32 local_id;
   u8 is_mrt_parse;
-  u8 is_interior;
-  u8 is_internal;
   const char *proto_name;
   u32 debug;                           /* Debugging flags */
   struct channel *mpls_channel;
@@ -512,8 +531,6 @@ struct bgp_parse_state {
   int allow_local_pref;
   int allow_local_as;
   int enforce_first_as;
-  u32 default_local_pref;
-  u32 confederation;
   u8 local_role;
   int rr_client;
   ip_addr remote_ip;
@@ -773,6 +790,7 @@ byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf);
 #define BAF_TRANSITIVE         0x40
 #define BAF_PARTIAL            0x20
 #define BAF_EXT_LEN            0x10
+#define BAF_OPERATIONAL 0x100
 
 #define BAF_DECODE_FLAGS       0x0100  /* Private flag - attribute flags are handled by the decode hook */
 
@@ -794,6 +812,7 @@ byte *bgp_create_end_mark_(struct bgp_channel *c, byte *buf);
 #define BA_AIGP                        0x1a    /* RFC 7311 */
 #define BA_LARGE_COMMUNITY     0x20    /* RFC 8092 */
 #define BA_ONLY_TO_CUSTOMER    0x23    /* RFC 9234 */
+#define BA_PROTO_ATTRS 0x24 /* BGP_PROTO_ATTRIBUTES */
 
 /* Bird's private internal BGP attributes */
 #define BA_MPLS_LABEL_STACK    0xfe    /* MPLS label stack transfer attribute */
index 93df8f9660ac902311b591778a478bfabd8c68a8..9c2eed3007ffb684e308ff57658cf1da97aa57bf 100644 (file)
@@ -14,10 +14,13 @@ CF_DEFINES
 
 #define BGP_CFG ((struct bgp_config *) this_proto)
 #define BGP_CC ((struct bgp_channel_config *) this_channel)
+#define BGP_RT_CF BGP_CFG->route_attrs;
 
 static struct ao_config *this_ao_key;
 static struct ao_config **next_ao_key;
 
+static struct rte_class_config *BGP_RT_CFG;
+
 CF_DECLS
 
 CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
@@ -55,6 +58,7 @@ proto: bgp_proto '}'  ;
 
 bgp_proto_start: proto_start BGP {
      this_proto = proto_config_new(&proto_bgp, $1);
+     BGP_RT_CFG = &BGP_CFG->rte_class;
      BGP_CFG->local_port = BGP_PORT;
      BGP_CFG->remote_port = BGP_PORT;
      BGP_CFG->multihop = -1;   /* undefined */
@@ -142,8 +146,19 @@ bgp_role_name:
  | RS_CLIENT { $$ = BGP_ROLE_RS_CLIENT; }
  ;
 
+bgp_attr_for_route:
+   DETERMINISTIC MED bool ';' { BGP_RT_CFG->deterministic_med = $3; }
+ | DEFAULT BGP_LOCAL_PREF expr ';' { BGP_RT_CFG->default_local_pref = $3; }
+ | PATH METRIC bool ';' { BGP_RT_CFG->compare_path_lengths = $3; }
+ | CONFEDERATION expr ';' { BGP_RT_CFG->confederation = $2; }
+ | MED METRIC bool ';' { BGP_RT_CFG->med_metric = $3; }
+ | DEFAULT BGP_MED expr ';' { BGP_RT_CFG->default_med = $3; }
+ | IGP METRIC bool ';' { BGP_RT_CFG->igp_metric = $3; }
+ | PREFER OLDER bool ';' { BGP_RT_CFG->prefer_older = $3; }
+
 bgp_proto:
-   bgp_proto_start proto_name '{'
+   bgp_proto bgp_attr_for_route
+ | bgp_proto_start proto_name '{'
  | bgp_proto proto_item ';'
  | bgp_proto bgp_proto_channel ';'
  | bgp_proto mpls_channel ';'
@@ -170,7 +185,6 @@ bgp_proto:
  | bgp_proto RR CLUSTER ID idval ';' { BGP_CFG->rr_cluster_id = $5; }
  | bgp_proto RR CLIENT bool ';' { BGP_CFG->rr_client = $4; }
  | bgp_proto RS CLIENT bool ';' { BGP_CFG->rs_client = $4; }
- | bgp_proto CONFEDERATION expr ';' { BGP_CFG->confederation = $3; }
  | bgp_proto CONFEDERATION MEMBER bool ';' { BGP_CFG->confederation_member = $4; }
  | bgp_proto HOLD TIME expr ';' { BGP_CFG->hold_time = $4; if (($4 && $4<3) || ($4>65535)) cf_error("Hold time must be in range 3-65535 or zero"); }
  | bgp_proto MIN HOLD TIME expr ';' { BGP_CFG->min_hold_time = $5; }
@@ -186,13 +200,6 @@ bgp_proto:
  | bgp_proto DYNAMIC NAME DIGITS expr ';' { BGP_CFG->dynamic_name_digits = $5; if ($5>10) cf_error("Dynamic name digits must be at most 10"); }
  | bgp_proto STRICT BIND bool ';' { BGP_CFG->strict_bind = $4; }
  | bgp_proto FREE BIND bool ';' { BGP_CFG->free_bind = $4; }
- | bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
- | bgp_proto MED METRIC bool ';' { BGP_CFG->med_metric = $4; }
- | bgp_proto IGP METRIC bool ';' { BGP_CFG->igp_metric = $4; }
- | bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; }
- | bgp_proto DETERMINISTIC MED bool ';' { BGP_CFG->deterministic_med = $4; }
- | bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; }
- | bgp_proto DEFAULT BGP_LOCAL_PREF expr ';' { BGP_CFG->default_local_pref = $4; }
  | bgp_proto SOURCE ADDRESS ipa ';' { BGP_CFG->local_ip = $4; }
  | bgp_proto START DELAY TIME expr ';' { BGP_CFG->connect_delay_time = $5; cf_warn("%s: Start delay time option is deprecated, use connect delay time", this_proto->name); }
  | bgp_proto CONNECT DELAY TIME expr ';' { BGP_CFG->connect_delay_time = $5; }
index 42af4c99bc17ac67a506c891963e2404d88c1d33..5b4cda16b8ff395b652b0d19707337b43b554dc6 100644 (file)
@@ -1177,7 +1177,7 @@ static void
 bgp_apply_flow_validation(struct bgp_parse_state *s, const net_addr *n, rta *a)
 {
   struct bgp_channel *c = SKIP_BACK(struct bgp_channel, c, s->channel);
-  int valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->is_interior);
+  int valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->proto_attrs->is_interior);
   a->dest = valid ? RTD_NONE : RTD_UNREACHABLE;
 
   /* Invalidate cached rta if dest changes */
@@ -2861,6 +2861,8 @@ bgp_parse_update(struct bgp_parse_state *s, byte *pkt, uint len, ea_list **ea)
   else
     *ea = NULL;
 
+  bgp_set_attr_ptr(ea, s->pool, BA_PROTO_ATTRS, 0, (adata*) s->proto_attrs);
+
   /* Check for End-of-RIB marker */
   if (!s->attr_len && !s->ip_unreach_len && !s->ip_reach_len)
   { s->end_mark(s, BGP_AF_IPV4); return; }
@@ -2917,25 +2919,18 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
     .get_channel = bgp_get_channel_to_parse,
     .apply_mpls_labels = bgp_apply_mpls_labels,
 
-    .local_as = p->local_as,
+    .proto_attrs = &p->proto_attrs,
     .remote_ip = p->remote_ip,
     .public_as = p->public_as,
-    .remote_as = p->remote_as,
-    .rr_cluster_id = p->rr_cluster_id,
-    .local_id = p->local_id,
-    .is_interior = p->is_interior,
-    .is_internal = p->is_internal,
     .proto_name = p->p.name,
     .is_mrt_parse = 0,
     .debug = p->p.debug,
     .mpls_channel = p->p.mpls_channel,
 
     // from config
-    .default_local_pref = p->cf->default_local_pref,
     .allow_local_pref = p->cf->allow_local_pref,
     .allow_as_sets = p->cf->allow_as_sets,
     .allow_local_as = p->cf->allow_local_as,
-    .confederation = p->cf->confederation,
     .enforce_first_as = p->cf->enforce_first_as,
     .local_role = p->cf->local_role,
     .rr_client = p->cf->rr_client,
index 1336837a80f4621fc7512db3f38b33b2706af7f9..c460e691346b0ce9e9ee0073d25b14c6fa7cbcc9 100644 (file)
@@ -351,6 +351,7 @@ mrt_peer_table_entry(struct mrt_table_dump_state *s, u32 peer_id, u32 peer_as, i
 static void
 mrt_peer_table_dump(struct mrt_table_dump_state *s)
 {
+  log("mrt_peer_table_dump");
   mrt_init_message(&s->buf, MRT_TABLE_DUMP_V2, MRT_PEER_INDEX_TABLE);
   mrt_peer_table_header(s, config->router_id, s->table->name);
 
index 9ef35bde075704b8771f1460d359d2defa2031d2..908eacadb9cf949f74a6dc7306a8556f91c1fc27 100644 (file)
@@ -83,6 +83,7 @@ mrt_parse_error(struct bgp_parse_state * ps UNUSED, uint e UNUSED)
 void
 mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4)
 {
+  log("mrt_parse_bgp_message");
   u64 peer_as, local_as;
   if (as4)
   {
@@ -97,6 +98,7 @@ mrt_parse_bgp_message(FILE *fp, u64 *remains, bool as4)
   int interface_id = mrtload_two_octet(fp, remains);
   int addr_fam = mrtload_two_octet(fp, remains);
 
+  log("peer as %i", peer_as);
   ip_addr peer_addr, local_addr;
   mrtload_ip(fp, remains, &peer_addr, addr_fam == 2);
   mrtload_ip(fp, remains, &local_addr, addr_fam == 2);
@@ -133,6 +135,7 @@ mrt_apply_mpls_labels(struct bgp_parse_state *s UNUSED, rta *a UNUSED, u32 *labe
 static void
 mrt_parse_bgp4mp_message(FILE *fp, u64 *remains, bool as4, struct proto *P)
 {
+  log("here");
   mrt_parse_bgp_message(fp, remains, as4);
 
   if (*remains < 19)
@@ -201,8 +204,10 @@ mrt_parse_general_header(FILE *fp, struct proto *P)
   u64 remains = length;
 
   /* We do not load MRT_TABLE_DUMP_V2 type and MRT_BGP4MP_STATE_CHANGE_AS4. */
+  log("type %i subtype %i", type, subtype);
   if (type == MRT_BGP4MP)
   {
+    log("yeah?");
     switch (subtype)
     {
       case (MRT_BGP4MP_MESSAGE):
@@ -232,12 +237,12 @@ mrt_parse_general_header(FILE *fp, struct proto *P)
 void
 mrtload(struct proto *P)
 {
-  struct mrt_config *cf = SKIP_BACK(struct mrt_config, c, P->cf);
+  struct mrtload_config *cf = (void *) (P->cf);
   FILE *fp = fopen(cf->filename, "r");
 
   if (fp == NULL)
   {
-    log(L_WARN "Can not open file %s", fp);
+    log(L_WARN "Can not open file %s", cf->filename);
     return;
   }
 
@@ -255,6 +260,8 @@ mrtload_check_config(struct proto_config *CF, struct bgp_channel_config *CC)
 
   if (!cf->filename)
     cf_error("File not specified");
+  else
+    log("%s", cf->filename);
 
   if (!CC->desc)
     cf_error("Afi not specified.");
@@ -276,6 +283,14 @@ mrtload_start(struct proto *P)
   struct mrtload_proto *p = (void *) P;
   struct mrtload_config *cf = (void *) (P->cf);
 
+  p->deterministic_med = cf->deterministic_med;
+  p->default_local_pref = cf->default_local_pref;
+  p->compare_path_lengths = cf->compare_path_lengths;
+  p->confederation = cf->confederation;
+  p->med_metric = cf->med_metric;
+  p->default_med = cf->default_med;
+  p->igp_metric = cf->igp_metric;
+  p->prefer_older = cf->prefer_older;
   p->channel = (void *) proto_add_channel(P, &cf->channel_cf->c);
 
   p->channel->afi = cf->channel_cf->afi;
index 6609d1c5b731420591139f7f5be244e97d469af8..64391cc4a1fb484183c110e1ccc1df826acd84c1 100644 (file)
@@ -13,6 +13,10 @@ extern const struct channel_class channel_mrtload;
 
 struct mrtload_config {
   struct proto_config c;
+  union {
+    struct rte_class_config rte_class;
+    struct { BGP_ROUTE_ATTRIBUTES };
+  };
 
   struct rtable_config *table_cf;
   const char *table_expr;
@@ -25,6 +29,10 @@ struct mrtload_config {
 
 struct mrtload_proto {
   struct proto p;
+    union {
+    struct rte_class_config rte_class;
+    struct { BGP_PROTO_ATTRIBUTES };
+  };
 
   struct mrt_table_dump_state *table_dump;
   struct bgp_channel *channel;
index 51eba5740409a6874ea7e08e394b0fcbd04ccc30..3bd29fb229b13514c12ef4a0ac3167fd233b2ab3 100644 (file)
@@ -21,6 +21,7 @@ proto: mrtload_proto;
 mrtload_proto_start: proto_start MRTLOAD
 {
   this_proto = proto_config_new(&proto_mrtload, $1);
+  BGP_RT_CFG = &MRTLOAD_CFG->rte_class;
 };
 
 
@@ -86,6 +87,7 @@ mrtload_proto_opts:
    /* empty */
  | mrtload_proto_opts mrt_get_bgp_channel mrtload_tab ';'
  | mrtload_proto_opts mrtload_proto_item ';'
+ | mrtload_proto_opts bgp_attr_for_route
  ;
 
 
index cc422ee1c2648238e6fe00dcef5cc71685b8c0fa..9387d3cfd217c18d20a894d4628d8e4524961a61 100644 (file)
@@ -922,7 +922,7 @@ sk_set_icmp6_filter(sock *s, int p1, int p2)
 void
 sk_log_error(sock *s, const char *p)
 {
-  log(L_ERR "%s: Socket error: %s%#m", p, s->err);
+  bug("%s: Socket error: %s%#m", p, s->err);
 }
 
 
@@ -1665,7 +1665,8 @@ sk_open(sock *s)
         log(L_WARN "Socket error: %s%#m", s->err);
 
     sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port);
-    if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
+    int i = bind(fd, &sa.sa, SA_LEN(sa));
+    if (i < 0)
       ERR2("bind");
   }