]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge commit '5cff1d5f' into haugesund
authorMaria Matejka <mq@ucw.cz>
Wed, 9 Mar 2022 09:56:06 +0000 (10:56 +0100)
committerMaria Matejka <mq@ucw.cz>
Wed, 9 Mar 2022 09:56:06 +0000 (10:56 +0100)
Conflicts:
      proto/bgp/attrs.c
      proto/pipe/pipe.c

1  2 
filter/config.Y
filter/data.h
filter/f-inst.c
nest/route.h
nest/rt-show.c
nest/rt-table.c
proto/babel/babel.c
proto/bgp/attrs.c
proto/bgp/packets.c
proto/pipe/pipe.c
sysdep/linux/netlink.c

diff --cc filter/config.Y
Simple merge
diff --cc filter/data.h
Simple merge
diff --cc filter/f-inst.c
Simple merge
diff --cc nest/route.h
index 75890a71af3dd3fb93638cbfc2e422cb91aa1ed7,1dea058f163407c66070d1d1c5611e3754ab1f65..19c1353857e4d94f4ac39df95ec9ff32de79db17
@@@ -348,11 -324,10 +348,11 @@@ static inline net *net_find(rtable *tab
  static inline net *net_find_valid(rtable *tab, const net_addr *addr)
  { net *n = net_find(tab, addr); return (n && rte_is_valid(n->routes)) ? n : NULL; }
  static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
 -void *net_route(rtable *tab, const net_addr *n);
 +net *net_get(rtable *tab, const net_addr *addr);
 +net *net_route(rtable *tab, const net_addr *n);
  int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
  rte *rte_find(net *net, struct rte_src *src);
- rte *rte_get_temp(struct rta *);
+ rte *rte_get_temp(struct rta *, struct rte_src *src);
  void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
  /* rte_update() moved to protocol.h to avoid dependency conflicts */
  int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter);
diff --cc nest/rt-show.c
Simple merge
diff --cc nest/rt-table.c
index 36bf1364b21af8786b86e1462e46cf13c8350bc5,a869bb1882510c811160a5895369bfea33fb87ab..65ff2a59152443d32331d358ed0554de3d69fefb
@@@ -2733,152 -2233,6 +2735,152 @@@ rt_next_hop_update_rte(rtable *tab UNUS
    return e;
  }
  
-   struct bgp_proto *p = (void *) r->attrs->src->proto;
 +
 +#ifdef CONFIG_BGP
 +
 +static inline int
 +net_flow_has_dst_prefix(const net_addr *n)
 +{
 +  ASSUME(net_is_flow(n));
 +
 +  if (n->pxlen)
 +    return 1;
 +
 +  if (n->type == NET_FLOW4)
 +  {
 +    const net_addr_flow4 *n4 = (void *) n;
 +    return (n4->length > sizeof(net_addr_flow4)) && (n4->data[0] == FLOW_TYPE_DST_PREFIX);
 +  }
 +  else
 +  {
 +    const net_addr_flow6 *n6 = (void *) n;
 +    return (n6->length > sizeof(net_addr_flow6)) && (n6->data[0] == FLOW_TYPE_DST_PREFIX);
 +  }
 +}
 +
 +static inline int
 +rta_as_path_is_empty(rta *a)
 +{
 +  eattr *e = ea_find(a->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
 +  return !e || (as_path_getlen(e->u.ptr) == 0);
 +}
 +
 +static inline u32
 +rta_get_first_asn(rta *a)
 +{
 +  eattr *e = ea_find(a->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
 +  u32 asn;
 +
 +  return (e && as_path_get_first_regular(e->u.ptr, &asn)) ? asn : 0;
 +}
 +
 +int
 +rt_flowspec_check(rtable *tab_ip, rtable *tab_flow, const net_addr *n, rta *a, int interior)
 +{
 +  ASSERT(rt_is_ip(tab_ip));
 +  ASSERT(rt_is_flow(tab_flow));
 +  ASSERT(tab_ip->trie);
 +
 +  /* RFC 8955 6. a) Flowspec has defined dst prefix */
 +  if (!net_flow_has_dst_prefix(n))
 +    return 0;
 +
 +  /* RFC 9117 4.1. Accept  AS_PATH is empty (fr */
 +  if (interior && rta_as_path_is_empty(a))
 +    return 1;
 +
 +
 +  /* RFC 8955 6. b) Flowspec and its best-match route have the same originator */
 +
 +  /* Find flowspec dst prefix */
 +  net_addr dst;
 +  if (n->type == NET_FLOW4)
 +    net_fill_ip4(&dst, net4_prefix(n), net4_pxlen(n));
 +  else
 +    net_fill_ip6(&dst, net6_prefix(n), net6_pxlen(n));
 +
 +  /* Find best-match BGP unicast route for flowspec dst prefix */
 +  net *nb = net_route(tab_ip, &dst);
 +  rte *rb = nb ? nb->routes : NULL;
 +
 +  /* Register prefix to trie for tracking further changes */
 +  int max_pxlen = (n->type == NET_FLOW4) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
 +  trie_add_prefix(tab_flow->flowspec_trie, &dst, (nb ? nb->n.addr->pxlen : 0), max_pxlen);
 +
 +  /* No best-match BGP route -> no flowspec */
 +  if (!rb || (rb->attrs->source != RTS_BGP))
 +    return 0;
 +
 +  /* Find ORIGINATOR_ID values */
 +  u32 orig_a = ea_get_int(a->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID), 0);
 +  u32 orig_b = ea_get_int(rb->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGINATOR_ID), 0);
 +
 +  /* Originator is either ORIGINATOR_ID (if present), or BGP neighbor address (if not) */
 +  if ((orig_a != orig_b) || (!orig_a && !orig_b && !ipa_equal(a->from, rb->attrs->from)))
 +    return 0;
 +
 +
 +  /* Find ASN of the best-match route, for use in next checks */
 +  u32 asn_b = rta_get_first_asn(rb->attrs);
 +  if (!asn_b)
 +    return 0;
 +
 +  /* RFC 9117 4.2. For EBGP, flowspec and its best-match route are from the same AS */
 +  if (!interior && (rta_get_first_asn(a) != asn_b))
 +    return 0;
 +
 +  /* RFC 8955 6. c) More-specific routes are from the same AS as the best-match route */
 +  TRIE_WALK(tab_ip->trie, subnet, &dst)
 +  {
 +    net *nc = net_find_valid(tab_ip, &subnet);
 +    if (!nc)
 +      continue;
 +
 +    rte *rc = nc->routes;
 +    if (rc->attrs->source != RTS_BGP)
 +      return 0;
 +
 +    if (rta_get_first_asn(rc->attrs) != asn_b)
 +      return 0;
 +  }
 +  TRIE_WALK_END;
 +
 +  return 1;
 +}
 +
 +#endif /* CONFIG_BGP */
 +
 +static rte *
 +rt_flowspec_update_rte(rtable *tab, rte *r)
 +{
 +#ifdef CONFIG_BGP
 +  if ((r->attrs->source != RTS_BGP) || !r->u.bgp.base_table)
 +    return NULL;
 +
 +  const net_addr *n = r->net->n.addr;
-   a->aflags = 0;
++  struct bgp_proto *p = (void *) r->src->proto;
 +  int valid = rt_flowspec_check(r->u.bgp.base_table, tab, n, r->attrs, p->is_interior);
 +  int dest = valid ? RTD_NONE : RTD_UNREACHABLE;
 +
 +  if (dest == r->attrs->dest)
 +    return NULL;
 +
 +  rta *a = alloca(RTA_MAX_SIZE);
 +  memcpy(a, r->attrs, rta_size(r->attrs));
 +  a->dest = dest;
++  a->cached = 0;
 +
 +  rte *new = sl_alloc(rte_slab);
 +  memcpy(new, r, sizeof(rte));
 +  new->attrs = rta_lookup(a);
 +
 +  return new;
 +#else
 +  return NULL;
 +#endif
 +}
 +
 +
  static inline int
  rt_next_hop_update_net(rtable *tab, net *n)
  {
Simple merge
index c35f9384ea5ccc85204966992c7c1bad32bd9c56,107060884b6773e1f5ce4a56473c2536dcc595bb..09c0bc570638962f9c037814d6429e92b7831614
@@@ -1861,7 -1846,9 +1861,7 @@@ bgp_rt_notify(struct proto *P, struct c
  
      /* If attributes are invalid, we fail back to withdraw */
      buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
-     path = new->attrs->src->global_id;
+     path = new->src->global_id;
 -
 -    lp_flush(bgp_linpool2);
    }
    else
    {
Simple merge
index cc4b5a0734ea6c9fd9adbe43c5373374687d7c2d,de86b62b6c044d1d2fb7e16b904703faf0030a58..636c3e58c36a13aaabd794bfcb1e9f4f7bbb13d2
@@@ -80,14 -81,9 +81,12 @@@ pipe_rt_notify(struct proto *P, struct 
  
  #ifdef CONFIG_BGP
        /* Hack to cleanup cached value */
-       if (e->attrs->src->proto->proto == &proto_bgp)
+       if (e->src->proto->proto == &proto_bgp)
 +      {
        e->u.bgp.stale = -1;
 +      e->u.bgp.base_table = NULL;
 +      }
  #endif
-       src = a->src;
      }
    else
      {
Simple merge