]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
OSPF: Allow ifaces with host address as unnumbered PtP or PtMP ifaces
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 10 May 2021 11:39:55 +0000 (13:39 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 10 May 2021 11:39:55 +0000 (13:39 +0200)
Ifaces with host address (/32) were forced to be stubby, but now they
can be used as PtP or PtMP. For these ifaces we need to:

 - Do not force stub mode
 - Accept packets from any IP as local
 - Accept any configured neighbor as local
 - Detect ifaces properly as unnumbered
 - Use ONLINK flag for nexthops

proto/ospf/iface.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/rt.c

index 666140b5ab8b6bd972f2405f188adf3962dee001..f38b8210c0b87f70be99181790d6a75dbbaf0b71 100644 (file)
@@ -529,14 +529,14 @@ add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
 }
 
 static int
-ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
+ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr, int type)
 {
   /* vlink cannot be stub */
-  if (ip->type == OSPF_IT_VLINK)
+  if (type == OSPF_IT_VLINK)
     return 0;
 
-  /* a host address */
-  if (addr->flags & IA_HOST)
+  /* Host address on Broadcast/NBMA */
+  if (((type == OSPF_IT_BCAST) || (type == OSPF_IT_NBMA)) && (addr->flags & IA_HOST))
     return 1;
 
   /* a loopback iface */
@@ -584,7 +584,6 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
   ifa->strictnbma = ip->strictnbma;
   ifa->waitint = ip->waitint;
   ifa->deadint = ip->deadint;
-  ifa->stub = ospf_iface_stubby(ip, addr);
   ifa->ioprob = OSPF_I_OK;
   ifa->check_link = ip->check_link;
   ifa->ecmp_weight = ip->ecmp_weight;
@@ -598,18 +597,19 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
   ifa->tx_length = ifa_tx_length(ifa);
   ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
 
-  ifa->ptp_netmask = !(addr->flags & IA_PEER);
+  ifa->ptp_netmask = !(addr->flags & (IA_HOST | IA_PEER));
   if (ip->ptp_netmask < 2)
     ifa->ptp_netmask = ip->ptp_netmask;
 
   /* For compatibility, we may use ptp_address even for unnumbered links */
-  ifa->ptp_address = !(addr->flags & IA_PEER) || (p->gr_mode != OSPF_GR_ABLE);
+  ifa->ptp_address = !(addr->flags & (IA_HOST | IA_PEER)) || (p->gr_mode != OSPF_GR_ABLE);
   if (ip->ptp_address < 2)
     ifa->ptp_address = ip->ptp_address;
 
   ifa->drip = ifa->bdrip = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6;
 
   ifa->type = ospf_iface_classify(ip->type, addr);
+  ifa->stub = ospf_iface_stubby(ip, addr, ifa->type);
 
   /* Check validity of interface type */
   int old_type = ifa->type;
@@ -647,7 +647,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
        should be used). Because OSPFv3 iface is not subnet-specific,
        there is no need for ipa_in_net() check */
 
-    if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &addr->prefix))
+    if (ospf_is_v2(p) && !ospf_ipa_local(nb->ip, addr))
       continue;
 
     if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
@@ -767,7 +767,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
   if (old_type != new_type)
     return 0;
 
-  int new_stub = ospf_iface_stubby(new, ifa->addr);
+  int new_stub = ospf_iface_stubby(new, ifa->addr, new_type);
   if (ifa->stub != new_stub)
     return 0;
 
@@ -929,7 +929,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
   WALK_LIST(nb, new->nbma_list)
   {
     /* See related note in ospf_iface_new() */
-    if (ospf_is_v2(p) && !ipa_in_netX(nb->ip, &ifa->addr->prefix))
+    if (ospf_is_v2(p) && !ospf_ipa_local(nb->ip, ifa->addr))
       continue;
 
     if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
@@ -1011,7 +1011,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
 
   /* PtP netmask */
   int new_ptp_netmask = (new->ptp_netmask < 2) ? new->ptp_netmask :
-    !(ifa->addr->flags & IA_PEER);
+    !(ifa->addr->flags & (IA_HOST | IA_PEER));
   if (ifa->ptp_netmask != new_ptp_netmask)
   {
     OSPF_TRACE(D_EVENTS, "Changing PtP netmask option of %s from %d to %d",
@@ -1021,7 +1021,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
 
   /* PtP address */
   int new_ptp_address = (new->ptp_address < 2) ? new->ptp_address :
-    (!(ifa->addr->flags & IA_PEER) || (p->gr_mode != OSPF_GR_ABLE));
+    (!(ifa->addr->flags & (IA_HOST | IA_PEER)) || (p->gr_mode != OSPF_GR_ABLE));
   if (ifa->ptp_address != new_ptp_address)
   {
     /* Keep it silent for implicit changes */
index fd2347e5539e494f25e5826b3d97fbe9f57d832b..3e704ae82e8dc95328ee55fb18c63ec8b59da7de 100644 (file)
@@ -946,6 +946,14 @@ struct lsadb_show_data {
 #define EA_OSPF_ROUTER_ID EA_CODE(PROTOCOL_OSPF, 3)
 
 
+/*
+ * For regular networks, neighbor address must match network prefix.
+ * For unnumbered networks, we consider every address local.
+ */
+static inline int ospf_ipa_local(ip_addr a, const struct ifa *addr)
+{ return ipa_in_netX(a, &addr->prefix) || (addr->flags & IA_HOST); }
+
+
 /* ospf.c */
 void ospf_schedule_rtcalc(struct ospf_proto *p);
 
index 15242318563616d8f85d26078af9ba83e2c5fec7..d7e10f3776755885aaa9d9655c6433e18404f830 100644 (file)
@@ -403,7 +403,7 @@ ospf_rx_hook(sock *sk, uint len)
     return 1;
 
   int src_local, dst_local, dst_mcast;
-  src_local = ipa_in_netX(sk->faddr, &ifa->addr->prefix);
+  src_local = ospf_ipa_local(sk->faddr, ifa->addr);
   dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
   dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
 
index b3e49a11540db58e79e09a1d2327c18d0d6510a5..17f8be7feae21d67412b83191d64ec5672952d43 100644 (file)
@@ -1827,7 +1827,12 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
        return NULL;
     }
 
-    return new_nexthop(p, nh, ifa->iface, ifa->ecmp_weight);
+    struct nexthop *nhs = new_nexthop(p, nh, ifa->iface, ifa->ecmp_weight);
+
+    if (ifa->addr->flags & IA_HOST)
+      nhs->flags = RNF_ONLINK;
+
+    return nhs;
   }
 
   /* The third case - bcast or nbma neighbor */
@@ -2031,8 +2036,9 @@ again1:
       for (nh = nf->n.nhs; nh; nh = nh->next)
        if (ipa_nonzero(nh->gw))
        {
-         neighbor *ng = neigh_find(&p->p, nh->gw, nh->iface, 0);
-         if (!ng || (ng->scope == SCOPE_HOST))
+         neighbor *nbr = neigh_find(&p->p, nh->gw, nh->iface,
+                                   (nh->flags & RNF_ONLINK) ? NEF_ONLINK : 0);
+         if (!nbr || (nbr->scope == SCOPE_HOST))
            { reset_ri(nf); break; }
        }
     }