]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Real broadcast mode for OSPFv2.
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 14 May 2012 09:47:41 +0000 (11:47 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 14 May 2012 09:47:41 +0000 (11:47 +0200)
doc/bird.sgml
proto/ospf/config.Y
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
proto/ospf/lsupd.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/packet.h

index 820ebaa267bc44cd0161ce54e0876bce713228bd..b43eb2630d830828f219a5e97a71d60cd14d5ccf 100644 (file)
@@ -1825,6 +1825,7 @@ protocol ospf &lt;name&gt; {
                        type [broadcast|bcast|pointopoint|ptp|
                                nonbroadcast|nbma|pointomultipoint|ptmp];
                        strict nonbroadcast &lt;switch&gt;;
+                       real broadcast &lt;switch&gt;;
                        check link &lt;switch&gt;;
                        ecmp weight &lt;num&gt;;
                        authentication [none|simple|cryptographic];
@@ -2058,6 +2059,16 @@ protocol ospf &lt;name&gt; {
         If set, don't send hello to any undefined neighbor. This switch
         is ignored on other than NBMA or PtMP networks. Default value is no.
 
+       <tag>real broadcast <m/switch/</tag>
+        In <cf/type broadcast/ or <cf/type ptp/ network
+        configuration, OSPF packets are sent as IP multicast
+        packets. This option changes the behavior to using
+        old-fashioned IP broadcast packets. This may be useful as a
+        workaround if IP multicast for some reason does not work or
+        does not work reliably. This is a non-standard option and
+        probably is not interoperable with other OSPF
+        implementations. Default value is no.
+
        <tag>check link <M>switch</M></tag>
         If set, a hardware link state (reported by OS) is taken into
         consideration. When a link disappears (e.g. an ethernet cable is
index 0c36b7f8b81e12b19892efc6de19d3ebab10ec8e..67b0785f5fb992ca8d71c9e7681e70ff1c6bb3a0 100644 (file)
@@ -130,7 +130,7 @@ CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
 CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
 CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
 CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
-CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE)
+CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL)
 
 %type <t> opttext
 %type <ld> lsadb_args
@@ -287,6 +287,7 @@ ospf_iface_item:
  | TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
  | TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
  | TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
+ | REAL BROADCAST bool { OSPF_PATT->real_bcast = $3; if (OSPF_VERSION != 2) cf_error("Real broadcast option requires OSPFv2"); }
  | TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
  | PRIORITY expr { OSPF_PATT->priority = $2 ; if (($2<0) || ($2>255)) cf_error("Priority must be in range 0-255"); }
  | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
index d04cb54c097410e29ae9e46eb369be3ab77455f4..f9ba28f659665bb2f12a3ced76d6691e89e92297 100644 (file)
@@ -303,7 +303,7 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
   {
   case OSPF_IT_BCAST:
   case OSPF_IT_PTP:
-    ospf_send_to(ifa, AllSPFRouters);
+    ospf_send_to_all(ifa);
     break;
 
   case OSPF_IT_NBMA:
index 405e49dfd879d508a4183da5377abef8681728c6..a6a0c6c11efa7ddf5e8e96d22d12440460ba31ff 100644 (file)
@@ -120,13 +120,24 @@ ospf_sk_open(struct ospf_iface *ifa)
   sk->saddr = ifa->addr->ip;
   if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
   {
-    sk->ttl = 1;       /* Hack, this will affect just multicast packets */
+    if (ifa->cf->real_bcast)
+    {
+      ifa->all_routers = ifa->addr->brd;
+
+      if (sk_set_broadcast(sk, 1) < 0)
+        goto err;
+    }
+    else
+    {
+      ifa->all_routers = AllSPFRouters;
+      sk->ttl = 1;     /* Hack, this will affect just multicast packets */
 
-    if (sk_setup_multicast(sk) < 0)
-      goto err;
+      if (sk_setup_multicast(sk) < 0)
+        goto err;
 
-    if (sk_join_group(sk, AllSPFRouters) < 0)
-      goto err;
+      if (sk_join_group(sk, ifa->all_routers) < 0)
+        goto err;
+    }
   }
 
   ifa->sk = sk;
@@ -265,7 +276,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
     OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
               ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
 
-  if ((ifa->type == OSPF_IT_BCAST) && ifa->sk)
+  if ((ifa->type == OSPF_IT_BCAST) && !ifa->cf->real_bcast && ifa->sk)
   {
     if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
       ospf_sk_join_dr(ifa);
@@ -536,6 +547,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
 
   /* Check validity of interface type */
   int old_type = ifa->type;
+  u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
 
 #ifdef OSPFv2
   if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
@@ -545,10 +557,10 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
     ifa->type = OSPF_IT_PTMP;
 #endif
 
-  if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & IF_MULTICAST))
+  if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
     ifa->type = OSPF_IT_NBMA;
 
-  if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & IF_MULTICAST))
+  if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag))
     ifa->type = OSPF_IT_PTMP;
 
   if (ifa->type != old_type)
@@ -628,6 +640,9 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
   if (ifa->stub != new_stub)
     return 0;
 
+  if (new->real_bcast != ifa->cf->real_bcast)
+    return 0;
+
   ifa->cf = new;
   ifa->marked = 0;
 
@@ -1099,11 +1114,15 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
 void
 ospf_iface_info(struct ospf_iface *ifa)
 {
-  char *strict = "";
+  char *more = "";
 
   if (ifa->strictnbma &&
       ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
-    strict = "(strict)";
+    more = " (strict)";
+
+  if (ifa->cf->real_bcast &&
+      ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
+    more = " (real)";
 
   if (ifa->type == OSPF_IT_VLINK)
   {
@@ -1124,11 +1143,10 @@ ospf_iface_info(struct ospf_iface *ifa)
 #else /* OSPFv3 */
     cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
 #endif
-    cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
+    cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
     cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
   }
-  cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
-         ifa->stub ? "(stub)" : "");
+  cli_msg(-1015, "\tState: %s%s", ospf_is[ifa->state], ifa->stub ? " (stub)" : "");
   cli_msg(-1015, "\tPriority: %u", ifa->priority);
   cli_msg(-1015, "\tCost: %u", ifa->cost);
   if (ifa->oa->po->ecmp)
index 53422e53a3d74c7c98ed5cac7c0784f42eaf5296..00c50cafb4d8884a72109fdc3c12a1a4825ab151 100644 (file)
@@ -97,7 +97,9 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
        if (ifa->type == OSPF_IT_BCAST)
        {
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-           ospf_send_to(ifa, AllSPFRouters);
+           ospf_send_to_all(ifa);
+         else if (ifa->cf->real_bcast)
+           ospf_send_to_bdr(ifa);
          else
            ospf_send_to(ifa, AllDRouters);
        }
@@ -124,7 +126,9 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
   if (ifa->type == OSPF_IT_BCAST)
   {
     if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-      ospf_send_to(ifa, AllSPFRouters);
+      ospf_send_to_all(ifa);
+    else if (ifa->cf->real_bcast)
+      ospf_send_to_bdr(ifa);
     else
       ospf_send_to(ifa, AllDRouters);
   }
index 325a8d00180feee61ebb69271e1cce7781a8bef8..f71c72d1d5186f4f94544b58e7e14fd8ae9c835c 100644 (file)
@@ -314,7 +314,9 @@ ospf_lsupd_flood(struct proto_ospf *po,
       {
       case OSPF_IT_BCAST:
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
-         ospf_send_to(ifa, AllSPFRouters);
+         ospf_send_to_all(ifa);
+       else if (ifa->cf->real_bcast)
+         ospf_send_to_bdr(ifa);
        else
          ospf_send_to(ifa, AllDRouters);
        break;
@@ -327,7 +329,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
        break;
 
       case OSPF_IT_PTP:
-       ospf_send_to(ifa, AllSPFRouters);
+       ospf_send_to_all(ifa);
        break;
 
       case OSPF_IT_PTMP:
index 96da9aa7f53f2f6875b196aad6072e509c97a61c..3bffaf91c435b79ca69abdd08eafbcd10d781171 100644 (file)
@@ -205,6 +205,7 @@ struct ospf_iface
   bird_clock_t csn_use;         /* Last time when packet with that CSN was sent */
 #endif
 
+  ip_addr all_routers;         /*  */
   ip_addr drip;                        /* Designated router */
   ip_addr bdrip;               /* Backup DR */
   u32 drid;
@@ -790,22 +791,23 @@ struct ospf_iface_patt
   u32 deadc;
   u32 deadint;
   u32 inftransdelay;
-  u32 priority;
-  u32 strictnbma;
   list nbma_list;
+  u32 priority;
   u32 voa;
   u32 vid;
   u16 rxbuf;
-  u8 check_link;
-  u8 ecmp_weight;
 #define OSPF_RXBUF_NORMAL 0
 #define OSPF_RXBUF_LARGE 1
 #define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
-  u32 autype;                  /* Not really used in OSPFv3 */
+  u16 autype;                  /* Not really used in OSPFv3 */
 #define OSPF_AUTH_NONE 0
 #define OSPF_AUTH_SIMPLE 1
 #define OSPF_AUTH_CRYPT 2
 #define OSPF_AUTH_CRYPT_SIZE 16
+  u8 strictnbma;
+  u8 check_link;
+  u8 ecmp_weight;
+  u8 real_bcast;               /* Not really used in OSPFv3 */
 
 #ifdef OSPFv2
   list *passwords;
index 7a26967f76ce8cf9fb0ac7c8f842102257f5301a..241a58f73831309f6080e5be6db4ed249132418e 100644 (file)
@@ -273,7 +273,7 @@ ospf_rx_hook(sock *sk, int size)
   int src_local, dst_local UNUSED, dst_mcast; 
   src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
   dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
-  dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters);
+  dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters);
 
 #ifdef OSPFv2
   /* First, we eliminate packets with strange address combinations.
@@ -287,6 +287,9 @@ ospf_rx_hook(sock *sk, int size)
   if (!dst_mcast && !dst_local)
     return 1;
 
+  /* Ignore my own broadcast packets */
+  if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
+    return 1;
 #else /* OSPFv3 */
 
   /* In OSPFv3, src_local and dst_local mean link-local. 
index c0185b9c3d296bc969091048501f1daa3845a797..fbcb4288a9c5f37e46c651c198b609e8bcdf51f8 100644 (file)
@@ -19,6 +19,8 @@ void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
 void ospf_send_to_bdr(struct ospf_iface *ifa);
 void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
 
+static inline void ospf_send_to_all(struct ospf_iface *ifa) { ospf_send_to(ifa, ifa->all_routers); }
+
 static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
 
 static inline unsigned