]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Unsetting route attributes without messing with type system
authorMaria Matejka <mq@ucw.cz>
Mon, 14 Mar 2022 10:13:48 +0000 (11:13 +0100)
committerMaria Matejka <mq@ucw.cz>
Wed, 6 Apr 2022 16:14:08 +0000 (18:14 +0200)
filter/f-inst.c
nest/route.h
nest/rt-attr.c
proto/bgp/attrs.c
proto/bgp/bgp.h

index e2212c5b96c93152d062658aa39ce0e23e574c30..0226f729cf373b3e860fea516611e2a2330b4b95 100644 (file)
       case EAF_TYPE_LC_SET:
        RESULT_(T_LCLIST, ad, e->u.ptr);
        break;
-      case EAF_TYPE_UNDEF:
-       RESULT_VOID;
-       break;
       default:
        bug("Unknown dynamic attribute type");
       }
     ACCESS_RTE;
     ACCESS_EATTRS;
 
-    {
-      struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr));
-
-      l->next = NULL;
-      l->flags = EALF_SORTED;
-      l->count = 1;
-      l->attrs[0].id = da.ea_code;
-      l->attrs[0].flags = 0;
-      l->attrs[0].type = EAF_TYPE_UNDEF;
-      l->attrs[0].originated = 1;
-      l->attrs[0].fresh = 1;
-      l->attrs[0].u.data = 0;
-
-      f_rta_cow(fs);
-      l->next = *fs->eattrs;
-      *fs->eattrs = l;
-    }
+    f_rta_cow(fs);
+    ea_unset_attr(fs->eattrs, fs->pool, 1, da.ea_code);
   }
 
   INST(FI_LENGTH, 1, 1) {      /* Get length of */
index 9fbac8982c4814e81165907139a2d621dabee8e9..bf25dcf94766961b73f0b3529a0934c551fc0048 100644 (file)
@@ -505,6 +505,7 @@ typedef struct eattr {
   byte type:5;                         /* Attribute type */
   byte originated:1;                   /* The attribute has originated locally */
   byte fresh:1;                                /* An uncached attribute (e.g. modified in export filter) */
+  byte undef:1;                                /* Explicitly undefined */
   union {
     uintptr_t data;
     const struct adata *ptr;           /* Attribute data elsewhere */
@@ -540,7 +541,6 @@ const char *ea_custom_name(uint ea);
 #define EAF_TYPE_PTR 0x0d              /* Pointer to an object */
 #define EAF_TYPE_EC_SET 0x0e           /* Set of pairs of u32's - ext. community list */
 #define EAF_TYPE_LC_SET 0x12           /* Set of triplets of u32's - large community list */
-#define EAF_TYPE_UNDEF 0x1f            /* `force undefined' entry */
 #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) */
 
@@ -610,27 +610,50 @@ void ea_format_bitfield(const struct eattr *a, byte *buf, int bufsize, const cha
     ea = NULL; \
 } while(0) \
 
+struct ea_one_attr_list {
+  ea_list l;
+  eattr a;
+};
+
 static inline eattr *
 ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val)
 {
-  ea_list *a = lp_alloc(pool, sizeof(ea_list) + sizeof(eattr));
-  eattr *e = &a->attrs[0];
+  struct ea_one_attr_list *ea = lp_alloc(pool, sizeof(*ea));
+  *ea = (struct ea_one_attr_list) {
+    .l.flags = EALF_SORTED,
+    .l.count = 1,
+    .l.next = *to,
 
-  a->flags = EALF_SORTED;
-  a->count = 1;
-  a->next = *to;
-  *to = a;
-
-  e->id = id;
-  e->type = type;
-  e->flags = flags;
+    .a.id = id,
+    .a.type = type,
+    .a.flags = flags,
+  };
 
   if (type & EAF_EMBEDDED)
-    e->u.data = (u32) val;
+    ea->a.u.data = val;
   else
-    e->u.ptr = (struct adata *) val;
+    ea->a.u.ptr = (struct adata *) val;
+
+  *to = &ea->l;
 
-  return e;
+  return &ea->a;
+}
+
+static inline void
+ea_unset_attr(ea_list **to, struct linpool *pool, _Bool local, uint code)
+{
+  struct ea_one_attr_list *ea = lp_alloc(pool, sizeof(*ea));
+  *ea = (struct ea_one_attr_list) {
+    .l.flags = EALF_SORTED,
+    .l.count = 1,
+    .l.next = *to,
+    .a.id = code,
+    .a.fresh = local,
+    .a.originated = local,
+    .a.undef = 1,
+  };
+
+  *to = &ea->l;
 }
 
 static inline void
index 2f0395c743f1cb2012fb3a5c48fd1b5cd434087a..22b45db93c0f0d5fb8e9eae09dc5254aafc0dbb0 100644 (file)
@@ -448,8 +448,7 @@ ea_find(ea_list *e, unsigned id)
 {
   eattr *a = ea__find(e, id & EA_CODE_MASK);
 
-  if (a && (a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF &&
-      !(id & EA_ALLOW_UNDEF))
+  if (a && a->undef && !(id & EA_ALLOW_UNDEF))
     return NULL;
   return a;
 }
@@ -516,7 +515,7 @@ ea_walk(struct ea_walk_state *s, uint id, uint max)
 
        BIT32_SET(s->visited, n);
 
-       if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
+       if (a->undef)
          continue;
 
        s->eattrs = e;
@@ -616,7 +615,7 @@ ea_do_prune(ea_list *e)
 
       /* Now s0 is the most recent version, s[-1] the oldest one */
       /* Drop undefs */
-      if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
+      if (s0->undef)
        continue;
 
       /* Copy the newest version to destination */
@@ -742,6 +741,7 @@ ea_same(ea_list *x, ea_list *y)
          a->type != b->type ||
          a->originated != b->originated ||
          a->fresh != b->fresh ||
+         a->undef != b->undef ||
          ((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data : !adata_same(a->u.ptr, b->u.ptr)))
        return 0;
     }
@@ -944,6 +944,10 @@ ea_show(struct cli *c, const eattr *e)
     {
       *pos++ = ':';
       *pos++ = ' ';
+
+      if (e->undef)
+       bsprintf(pos, "undefined");
+      else
       switch (e->type & EAF_TYPE_MASK)
        {
        case EAF_TYPE_INT:
@@ -973,7 +977,6 @@ ea_show(struct cli *c, const eattr *e)
        case EAF_TYPE_LC_SET:
          ea_show_lc_set(c, ad, pos, buf, end);
          return;
-       case EAF_TYPE_UNDEF:
        default:
          bsprintf(pos, "<type %02x>", e->type);
        }
index 0513dd7c2378587e9f6653ba54dd0cd5a8d78c46..454686cf3344141b23c85aaeb9ff9ba624a93155 100644 (file)
@@ -106,7 +106,7 @@ bgp_set_attr(ea_list **attrs, struct linpool *pool, uint code, uint flags, uintp
   ({ REPORT(msg, ## args); s->err_withdraw = 1; return; })
 
 #define UNSET(a) \
-  ({ a->type = EAF_TYPE_UNDEF; return; })
+  ({ a->undef = 1; return; })
 
 #define REJECT(msg, args...) \
   ({ log(L_ERR "%s: " msg, s->proto->p.name, ## args); s->err_reject = 1; return; })
@@ -1161,7 +1161,7 @@ bgp_export_attr(struct bgp_export_state *s, eattr *a, ea_list *to)
     CALL(desc->export, s, a);
 
     /* Attribute might become undefined in hook */
-    if ((a->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
+    if (a->undef)
       return;
   }
   else
index bff49c3a455772d13f1b12beb918bfc281cf6e22..8a44514cc17441c0d54c086ec9e2e7dc2509b6f7 100644 (file)
@@ -563,9 +563,7 @@ bgp_set_attr_data(ea_list **to, struct linpool *pool, uint code, uint flags, voi
   bgp_set_attr(to, pool, code, flags, (uintptr_t) a);
 }
 
-static inline void
-bgp_unset_attr(ea_list **to, struct linpool *pool, uint code)
-{ eattr *e = bgp_set_attr(to, pool, code, 0, 0); e->type = EAF_TYPE_UNDEF; }
+#define bgp_unset_attr(to, pool, code) ea_unset_attr(to, pool, 0, code)
 
 int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);