summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-12-24 18:08:07 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2010-12-24 18:08:07 +0100
commit919f5411c48f509a49400a1293e670f5d5d2bcf1 (patch)
tree0701f270439c2e71a017c75f3095367db724ca8e
parent39847cda73d8e8536300b74d90d01b6e2f233ef7 (diff)
Implements Point-to-MultiPoint interface type for OSPF.
-rw-r--r--doc/bird.sgml58
-rw-r--r--proto/ospf/config.Y10
-rw-r--r--proto/ospf/hello.c134
-rw-r--r--proto/ospf/iface.c99
-rw-r--r--proto/ospf/iface.h5
-rw-r--r--proto/ospf/lsupd.c21
-rw-r--r--proto/ospf/neighbor.c29
-rw-r--r--proto/ospf/neighbor.h2
-rw-r--r--proto/ospf/ospf.c28
-rw-r--r--proto/ospf/ospf.h10
-rw-r--r--proto/ospf/packet.c15
-rw-r--r--proto/ospf/rt.c7
-rw-r--r--proto/ospf/topology.c43
13 files changed, 255 insertions, 206 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index c7816f08..5d9c7bd6 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -407,8 +407,8 @@ to zero to disable it. An empty <cf><m/switch/</cf> is equivalent to <cf/on/
<cf>interface "*" { type broadcast; };</cf> - start the protocol on all interfaces with
<cf>type broadcast</cf> option.
- <cf>interface "eth1", "eth4", "eth5" { type pointopoint; };</cf> - start the protocol
- on enumerated interfaces with <cf>type pointopoint</cf> option.
+ <cf>interface "eth1", "eth4", "eth5" { type ptp; };</cf> - start the protocol
+ on enumerated interfaces with <cf>type ptp</cf> option.
<cf>interface -192.168.1.0/24, 192.168.0.0/16;</cf> - start the protocol on all
interfaces that have address from 192.168.0.0/16, but not
@@ -1549,7 +1549,8 @@ protocol ospf &lt;name&gt; {
dead count &lt;num&gt;;
dead &lt;num&gt;;
rx buffer [normal|large|&lt;num&gt;];
- type [broadcast|nonbroadcast|pointopoint];
+ type [broadcast|bcast|pointopoint|ptp|
+ nonbroadcast|nbma|pointomultipoint|ptmp];
strict nonbroadcast &lt;switch&gt;;
check link &lt;switch&gt;;
ecmp weight &lt;num&gt;;
@@ -1688,23 +1689,43 @@ protocol ospf &lt;name&gt; {
be bigger than maximal size of any packets. Value NORMAL (default)
means 2*MTU, value LARGE means maximal allowed packet - 65535.
- <tag>type broadcast</tag>
- BIRD detects a type of a connected network automatically, but sometimes it's
- convenient to force use of a different type manually.
- On broadcast networks, flooding and Hello messages are sent using multicasts
- (a single packet for all the neighbors).
-
- <tag>type pointopoint</tag>
- Point-to-point networks connect just 2 routers together. No election
- is performed there which reduces the number of messages sent.
-
- <tag>type nonbroadcast</tag>
- On nonbroadcast networks, the packets are sent to each neighbor
+ <tag>type broadcast|bcast</tag>
+ BIRD detects a type of a connected network automatically, but
+ sometimes it's convenient to force use of a different type
+ manually. On broadcast networks (like ethernet), flooding
+ and Hello messages are sent using multicasts (a single packet
+ for all the neighbors). A designated router is elected and it
+ is responsible for synchronizing the link-state databases and
+ originating network LSAs. This network type cannot be used on
+ physically NBMA networks and on unnumbered networks (networks
+ without proper IP prefix).
+
+ <tag>type pointopoint|ptp</tag>
+ Point-to-point networks connect just 2 routers together. No
+ election is performed and no network LSA is originated, which
+ makes it simpler and faster to establish. This network type
+ is useful not only for physically PtP ifaces (like PPP or
+ tunnels), but also for broadcast networks used as PtP links.
+ This network type cannot be used on physically NBMA networks.
+
+ <tag>type nonbroadcast|nbma</tag>
+ On NBMA networks, the packets are sent to each neighbor
separately because of lack of multicast capabilities.
+ Like on broadcast networks, a designated router is elected,
+ which plays a central role in propagation of LSAs.
+ This network type cannot be used on unnumbered networks.
+
+ <tag>type pointomultipoint|ptmp</tag>
+ This is another network type designed to handle NBMA
+ networks. In this case the NBMA network is treated as a
+ collection of PtP links. This is useful if not every pair of
+ routers on the NBMA network has direct communication, or if
+ the NBMA network is used as an (possibly unnumbered) PtP
+ link.
<tag>strict nonbroadcast <M>switch</M></tag>
If set, don't send hello to any undefined neighbor. This switch
- is ignored on any non-NBMA network. Default value is no.
+ is ignored on other than NBMA or PtMP networks. Default value is no.
<tag>check link <M>switch</M></tag>
If set, a hardware link state (reported by OS) is taken into
@@ -1738,8 +1759,9 @@ protocol ospf &lt;name&gt; {
See <ref id="dsc-pass" name="password"> common option for detailed description.
<tag>neighbors { <m/set/ } </tag>
- A set of neighbors to which Hello messages on nonbroadcast networks
- are to be sent. Some of them could be marked as eligible.
+ A set of neighbors to which Hello messages on NBMA or PtMP
+ networks are to be sent. For NBMA networks, some of them
+ could be marked as eligible.
</descrip>
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y
index 59e1fbe0..321bd8d4 100644
--- a/proto/ospf/config.Y
+++ b/proto/ospf/config.Y
@@ -46,8 +46,9 @@ finish_iface_config(struct ospf_iface_patt *ip)
CF_DECLS
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
-CF_KEYWORDS(BROADCAST, NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
-CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE)
+CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
+CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
+CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
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)
@@ -190,8 +191,13 @@ ospf_iface_item:
| DEAD expr { OSPF_PATT->dead = $2 ; if ($2<=1) cf_error("Dead interval must be greater than one"); }
| DEAD COUNT expr { OSPF_PATT->deadc = $3 ; if ($3<=1) cf_error("Dead count must be greater than one"); }
| TYPE BROADCAST { OSPF_PATT->type = OSPF_IT_BCAST ; }
+ | TYPE BCAST { OSPF_PATT->type = OSPF_IT_BCAST ; }
| TYPE NONBROADCAST { OSPF_PATT->type = OSPF_IT_NBMA ; }
+ | TYPE NBMA { OSPF_PATT->type = OSPF_IT_NBMA ; }
| TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; }
+ | TYPE PTP { OSPF_PATT->type = OSPF_IT_PTP ; }
+ | TYPE POINTOMULTIPOINT { OSPF_PATT->type = OSPF_IT_PTMP ; }
+ | TYPE PTMP { OSPF_PATT->type = OSPF_IT_PTMP ; }
| STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| STUB bool { OSPF_PATT->stub = $2 ; }
| CHECK LINK bool { OSPF_PATT->check_link = $3; }
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c
index 216dc72f..47b84a4d 100644
--- a/proto/ospf/hello.c
+++ b/proto/ospf/hello.c
@@ -48,7 +48,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
char *beg = "OSPF: Bad HELLO packet from ";
- unsigned int size, i, twoway, eligible, peers;
+ unsigned int size, i, twoway, peers;
u32 tmp;
u32 *pnrid;
@@ -103,37 +103,30 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
if (!n)
{
- if ((ifa->type == OSPF_IT_NBMA))
+ if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
{
- struct nbma_node *nn;
- int found = 0;
+ struct nbma_node *nn = find_nbma_node(ifa, faddr);
- WALK_LIST(nn, ifa->nbma_list)
- {
- if (ipa_equal(faddr, nn->ip))
- {
- found = 1;
- break;
- }
- }
- if ((found == 0) && (ifa->strictnbma))
+ if (!nn && ifa->strictnbma)
{
log(L_WARN "Ignoring new neighbor: %I on %s", faddr,
ifa->iface->name);
return;
}
- if (found)
+
+ if (nn && (ifa->type == OSPF_IT_NBMA) &&
+ (((ps->priority == 0) && nn->eligible) ||
+ ((ps->priority > 0) && !nn->eligible)))
{
- eligible = nn->eligible;
- if (((ps->priority == 0) && eligible)
- || ((ps->priority > 0) && (eligible == 0)))
- {
- log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
- faddr, ifa->iface->name);
- return;
- }
+ log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
+ faddr, ifa->iface->name);
+ return;
}
+
+ if (nn)
+ nn->found = 1;
}
+
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr,
ifa->iface->name);
@@ -239,7 +232,7 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
struct ospf_neighbor *neigh, *n1;
u16 length;
u32 *pp;
- int i, send;
+ int i;
struct nbma_node *nb;
if (timer == NULL)
@@ -311,53 +304,56 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
switch(ifa->type)
{
- case OSPF_IT_NBMA:
- if (timer == NULL) /* Response to received hello */
- {
- ospf_send_to(ifa, dirn->ip);
- }
- else
- {
- int toall = 0;
- int meeli = 0;
- if (ifa->state > OSPF_IS_DROTHER)
- toall = 1;
- if (ifa->priority > 0)
- meeli = 1;
-
- WALK_LIST(nb, ifa->nbma_list)
- {
- send = 1;
- WALK_LIST(n1, ifa->neigh_list)
- {
- if (ipa_equal(nb->ip, n1->ip))
- {
- send = 0;
- break;
- }
- }
- if ((poll == 1) && (send))
- {
- if (toall || (meeli && nb->eligible))
- ospf_send_to(ifa, nb->ip);
- }
- }
- if (poll == 0)
- {
- WALK_LIST(n1, ifa->neigh_list)
- {
- if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
- (meeli && (n1->priority > 0)))
- ospf_send_to(ifa, n1->ip);
- }
- }
- }
- break;
- case OSPF_IT_VLINK:
- ospf_send_to(ifa, ifa->vip);
+ case OSPF_IT_BCAST:
+ case OSPF_IT_PTP:
+ ospf_send_to(ifa, AllSPFRouters);
+ break;
+
+ case OSPF_IT_NBMA:
+ if (timer == NULL) /* Response to received hello */
+ {
+ ospf_send_to(ifa, dirn->ip);
break;
- default:
- ospf_send_to(ifa, AllSPFRouters);
+ }
+
+ int to_all = ifa->state > OSPF_IS_DROTHER;
+ int me_elig = ifa->priority > 0;
+
+ if (poll) /* Poll timer */
+ {
+ WALK_LIST(nb, ifa->nbma_list)
+ if (!nb->found && (to_all || (me_elig && nb->eligible)))
+ ospf_send_to(ifa, nb->ip);
+ }
+ else /* Hello timer */
+ {
+ WALK_LIST(n1, ifa->neigh_list)
+ if (to_all || (me_elig && (n1->priority > 0)) ||
+ (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid))
+ ospf_send_to(ifa, n1->ip);
+ }
+ break;
+
+ case OSPF_IT_PTMP:
+ WALK_LIST(n1, ifa->neigh_list)
+ ospf_send_to(ifa, n1->ip);
+
+ WALK_LIST(nb, ifa->nbma_list)
+ if (!nb->found)
+ ospf_send_to(ifa, nb->ip);
+
+ /* If there is no other target, we also send HELLO packet to the other end */
+ if (ipa_nonzero(ifa->addr->opposite) && !ifa->strictnbma &&
+ EMPTY_LIST(ifa->neigh_list) && EMPTY_LIST(ifa->nbma_list))
+ ospf_send_to(ifa, ifa->addr->opposite);
+ break;
+
+ case OSPF_IT_VLINK:
+ ospf_send_to(ifa, ifa->vip);
+ break;
+
+ default:
+ bug("Bug in ospf_hello_send()");
}
OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s",
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 8b21f94b..05442dfe 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -8,7 +8,7 @@
#include "ospf.h"
-char *ospf_is[] = { "down", "loop", "waiting", "point-to-point", "drother",
+char *ospf_is[] = { "down", "loop", "waiting", "ptp", "drother",
"backup", "dr"
};
@@ -16,7 +16,7 @@ char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen",
"neighbor change", "loop indicated", "unloop indicated", "interface down"
};
-char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" };
+char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
static void
poll_timer_hook(timer * timer)
@@ -57,8 +57,18 @@ rxbufsize(struct ospf_iface *ifa)
}
}
+struct nbma_node *
+find_nbma_node_in(list *nnl, ip_addr ip)
+{
+ struct nbma_node *nn;
+ WALK_LIST(nn, *nnl)
+ if (ipa_equal(nn->ip, ip))
+ return nn;
+ return NULL;
+}
+
static int
-ospf_sk_open(struct ospf_iface *ifa)
+ospf_sk_open(struct ospf_iface *ifa, int multicast)
{
sock *sk = sk_new(ifa->pool);
sk->type = SK_IP;
@@ -106,11 +116,16 @@ ospf_sk_open(struct ospf_iface *ifa)
*/
sk->saddr = ifa->addr->ip;
- if (sk_setup_multicast(sk) < 0)
- goto err;
+ if (multicast)
+ {
+ if (sk_setup_multicast(sk) < 0)
+ goto err;
+
+ if (sk_join_group(sk, AllSPFRouters) < 0)
+ goto err;
+ }
ifa->sk = sk;
- ifa->sk_spf = 0;
ifa->sk_dr = 0;
return 1;
@@ -120,16 +135,6 @@ ospf_sk_open(struct ospf_iface *ifa)
}
static inline void
-ospf_sk_join_spf(struct ospf_iface *ifa)
-{
- if (ifa->sk_spf)
- return;
-
- sk_join_group(ifa->sk, AllSPFRouters);
- ifa->sk_spf = 1;
-}
-
-static inline void
ospf_sk_join_dr(struct ospf_iface *ifa)
{
if (ifa->sk_dr)
@@ -138,17 +143,6 @@ ospf_sk_join_dr(struct ospf_iface *ifa)
sk_join_group(ifa->sk, AllDRouters);
ifa->sk_dr = 1;
}
-
-static inline void
-ospf_sk_leave_spf(struct ospf_iface *ifa)
-{
- if (!ifa->sk_spf)
- return;
-
- sk_leave_group(ifa->sk, AllSPFRouters);
- ifa->sk_spf = 0;
-}
-
static inline void
ospf_sk_leave_dr(struct ospf_iface *ifa)
{
@@ -291,7 +285,7 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
if (ifa->state <= OSPF_IS_LOOP)
{
/* Now, nothing should be adjacent */
- if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
+ if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP) || (ifa->type == OSPF_IT_VLINK))
{
ospf_iface_chstate(ifa, OSPF_IS_PTP);
}
@@ -355,11 +349,11 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
}
-u8
-ospf_iface_clasify(struct iface *ifa, struct ifa *addr)
+static u8
+ospf_iface_classify(struct iface *ifa, struct ifa *addr)
{
if (ipa_nonzero(addr->opposite))
- return OSPF_IT_PTP;
+ return (ifa->flags & IF_MULTICAST) ? OSPF_IT_PTP : OSPF_IT_PTMP;
if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
(IF_MULTIACCESS | IF_MULTICAST))
@@ -388,12 +382,8 @@ ospf_iface_add(struct object_lock *lock)
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
- if (ospf_sk_open(ifa))
- {
- if (ifa->type != OSPF_IT_NBMA)
- ospf_sk_join_spf(ifa);
- }
- else
+ int mc = (ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP);
+ if (! ospf_sk_open(ifa, mc))
{
log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->iface->name);
ifa->ioprob = OSPF_I_SK;
@@ -448,7 +438,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
#endif
if (ip->type == OSPF_IT_UNDEF)
- ifa->type = ospf_iface_clasify(iface, addr);
+ ifa->type = ospf_iface_classify(iface, addr);
else
ifa->type = ip->type;
@@ -456,16 +446,28 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
if ((addr->pxlen == MAX_PREFIX_LENGTH) && ipa_zero(addr->opposite))
ifa->stub = 1;
+ /* Check validity of interface type */
+ int old_type = ifa->type;
+
#ifdef OSPFv2
- if ((ifa->type != OSPF_IT_PTP) && (ifa->type != OSPF_IT_VLINK) &&
- (addr->flags & IA_UNNUMBERED))
- {
- log(L_WARN "%s: Missing proper IP prefix on interface %s, forcing point-to-point mode",
- p->name, iface->name);
+ if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_UNNUMBERED))
ifa->type = OSPF_IT_PTP;
- }
+
+ if ((ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_UNNUMBERED))
+ ifa->type = OSPF_IT_PTMP;
#endif
+ if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & IF_MULTICAST))
+ ifa->type = OSPF_IT_NBMA;
+
+ if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & IF_MULTICAST))
+ ifa->type = OSPF_IT_PTMP;
+
+ if (ifa->type != old_type)
+ log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
+ p->name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
+
+
init_list(&ifa->neigh_list);
init_list(&ifa->nbma_list);
@@ -477,6 +479,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
nbma = mb_alloc(pool, sizeof(struct nbma_node));
nbma->ip = nb->ip;
nbma->eligible = nb->eligible;
+ nbma->found = 0;
add_tail(&ifa->nbma_list, NODE nbma);
}
@@ -766,10 +769,12 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
void
ospf_iface_info(struct ospf_iface *ifa)
{
- char *strict = "(strict)";
+ char *strict = "";
+
+ if (ifa->strictnbma &&
+ ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
+ strict = "(strict)";
- if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0))
- strict = "";
if (ifa->type == OSPF_IT_VLINK)
{
cli_msg(-1015, "Virtual link to %R:", ifa->vid);
diff --git a/proto/ospf/iface.h b/proto/ospf/iface.h
index 38a81486..f9631eb3 100644
--- a/proto/ospf/iface.h
+++ b/proto/ospf/iface.h
@@ -21,6 +21,11 @@ void ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr
void ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa);
void ospf_set_rxbuf_size(struct ospf_iface *ifa, u32 rxbuf);
+struct nbma_node *find_nbma_node_in(list *nnl, ip_addr ip);
+
+static inline struct nbma_node *
+find_nbma_node(struct ospf_iface *ifa, ip_addr ip)
+{ return find_nbma_node_in(&ifa->nbma_list, ip); }
#endif /* _BIRD_OSPF_IFACE_H_ */
diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c
index fb757d08..06b62ae2 100644
--- a/proto/ospf/lsupd.c
+++ b/proto/ospf/lsupd.c
@@ -304,6 +304,13 @@ ospf_lsupd_flood(struct proto_ospf *po,
switch (ifa->type)
{
+ case OSPF_IT_BCAST:
+ if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
+ ospf_send_to(ifa, AllSPFRouters);
+ else
+ ospf_send_to(ifa, AllDRouters);
+ break;
+
case OSPF_IT_NBMA:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
@@ -311,16 +318,20 @@ ospf_lsupd_flood(struct proto_ospf *po,
ospf_send_to_bdr(ifa);
break;
+ case OSPF_IT_PTP:
+ ospf_send_to(ifa, AllSPFRouters);
+ break;
+
+ case OSPF_IT_PTMP:
+ ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
+ break;
+
case OSPF_IT_VLINK:
ospf_send_to(ifa, ifa->vip);
break;
default:
- if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
- (ifa->type == OSPF_IT_PTP))
- ospf_send_to(ifa, AllSPFRouters);
- else
- ospf_send_to(ifa, AllDRouters);
+ bug("Bug in ospf_lsupd_flood()");
}
}
}
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index 05f024a7..98c9de50 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -276,6 +276,7 @@ can_do_adj(struct ospf_neighbor *n)
switch (ifa->type)
{
case OSPF_IT_PTP:
+ case OSPF_IT_PTMP:
case OSPF_IT_VLINK:
i = 1;
break;
@@ -531,9 +532,19 @@ struct ospf_neighbor *
find_neigh(struct ospf_iface *ifa, u32 rid)
{
struct ospf_neighbor *n;
+ WALK_LIST(n, ifa->neigh_list)
+ if (n->rid == rid)
+ return n;
+ return NULL;
+}
- WALK_LIST(n, ifa->neigh_list) if (n->rid == rid)
- return n;
+struct ospf_neighbor *
+find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
+{
+ struct ospf_neighbor *n;
+ WALK_LIST(n, ifa->neigh_list)
+ if (ipa_equal(n->ip, ip))
+ return n;
return NULL;
}
@@ -543,7 +554,7 @@ ospf_find_area(struct proto_ospf *po, u32 aid)
struct ospf_area *oa;
WALK_LIST(oa, po->area_list)
if (((struct ospf_area *) oa)->areaid == aid)
- return oa;
+ return oa;
return NULL;
}
@@ -567,6 +578,13 @@ ospf_neigh_remove(struct ospf_neighbor *n)
struct ospf_iface *ifa = n->ifa;
struct proto *p = &ifa->oa->po->proto;
+ if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
+ {
+ struct nbma_node *nn = find_nbma_node(ifa, n->ip);
+ if (nn)
+ nn->found = 0;
+ }
+
s_get(&(n->dbsi));
neigh_chstate(n, NEIGHBOR_DOWN);
rem_node(NODE n);
@@ -596,9 +614,10 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
if (n->rid == ifa->drid)
pos = "dr ";
- if (n->rid == ifa->bdrid)
+ else if (n->rid == ifa->bdrid)
pos = "bdr ";
- if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK))
+ else if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_PTMP) ||
+ (n->ifa->type == OSPF_IT_VLINK))
pos = "ptp ";
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
diff --git a/proto/ospf/neighbor.h b/proto/ospf/neighbor.h
index 5612eca1..dcaa12df 100644
--- a/proto/ospf/neighbor.h
+++ b/proto/ospf/neighbor.h
@@ -14,9 +14,9 @@ struct ospf_neighbor *ospf_neighbor_new(struct ospf_iface *ifa);
void ospf_neigh_sm(struct ospf_neighbor *n, int event);
void bdr_election(struct ospf_iface *ifa);
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid);
+struct ospf_neighbor *find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip);
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
void ospf_neigh_remove(struct ospf_neighbor *n);
void ospf_sh_neigh_info(struct ospf_neighbor *n);
-
#endif /* _BIRD_OSPF_NEIGHBOR_H_ */
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index 19e68e24..e10a405c 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -649,7 +649,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct ospf_iface *ifa;
struct nbma_node *nb1, *nb2, *nbnx;
struct ospf_area *oa = NULL;
- int found, olddead, newdead;
+ int olddead, newdead;
if (po->rfc1583 != new->rfc1583)
return 0;
@@ -881,19 +881,17 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
/* First remove old */
WALK_LIST_DELSAFE(nb1, nbnx, ifa->nbma_list)
{
- found = 0;
- WALK_LIST(nb2, newip->nbma_list)
- if (ipa_equal(nb1->ip, nb2->ip))
+ nb2 = find_nbma_node_in(&newip->nbma_list, nb1->ip);
+ if (nb2)
{
- found = 1;
if (nb1->eligible != nb2->eligible)
- OSPF_TRACE(D_EVENTS,
- "Changing neighbor eligibility %I on interface %s",
+ {
+ nb1->eligible = nb2->eligible;
+ OSPF_TRACE(D_EVENTS, "Changing neighbor eligibility %I on interface %s",
nb1->ip, ifa->iface->name);
- break;
+ }
}
-
- if (!found)
+ else
{
OSPF_TRACE(D_EVENTS,
"Removing NBMA neighbor %I on interface %s",
@@ -908,18 +906,12 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
if (!ipa_in_net(nb2->ip, ifa->addr->prefix, ifa->addr->pxlen))
continue;
- found = 0;
- WALK_LIST(nb1, ifa->nbma_list)
- if (ipa_equal(nb1->ip, nb2->ip))
- {
- found = 1;
- break;
- }
- if (!found)
+ if (find_nbma_node(ifa, nb2->ip) == NULL)
{
nb1 = mb_alloc(ifa->pool, sizeof(struct nbma_node));
nb1->ip = nb2->ip;
nb1->eligible = nb2->eligible;
+ nb1->found = !!find_neigh_by_ip(ifa, nb1->ip);
add_tail(&ifa->nbma_list, NODE nb1);
OSPF_TRACE(D_EVENTS,
"Adding NBMA neighbor %I on interface %s",
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index 2ef0180c..e260dc08 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -90,7 +90,8 @@ struct nbma_node
{
node n;
ip_addr ip;
- int eligible;
+ byte eligible;
+ byte found;
};
struct area_net_config
@@ -205,8 +206,9 @@ struct ospf_iface
#define OSPF_IT_BCAST 0
#define OSPF_IT_NBMA 1
#define OSPF_IT_PTP 2
-#define OSPF_IT_VLINK 3
-#define OSPF_IT_UNDEF 4
+#define OSPF_IT_PTMP 3
+#define OSPF_IT_VLINK 4
+#define OSPF_IT_UNDEF 5
u8 strictnbma; /* Can I talk with unknown neighbors? */
u8 stub; /* Inactive interface */
u8 state; /* Interface state machine */
@@ -245,7 +247,7 @@ struct ospf_iface
#define OSPF_I_OK 0 /* Everything OK */
#define OSPF_I_SK 1 /* Socket open failed */
#define OSPF_I_LL 2 /* Missing link-local address (OSPFv3) */
- u8 sk_spf; /* Socket is a member of SPFRouters group */
+ // u8 sk_spf; /* Socket is a member of SPFRouters group */
u8 sk_dr; /* Socket is a member of DRouters group */
u16 rxbuf; /* Buffer size */
u8 check_link; /* Whether iface link change is used */
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c
index bfc17d76..e8ebafd8 100644
--- a/proto/ospf/packet.c
+++ b/proto/ospf/packet.c
@@ -240,19 +240,6 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
#endif
-#ifdef OSPFv2
-static inline struct ospf_neighbor *
-find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
-{
- struct ospf_neighbor *n;
- WALK_LIST(n, ifa->neigh_list)
- if (ipa_equal(n->ip, ip))
- return n;
- return NULL;
-}
-#endif
-
-
/**
* ospf_rx_hook
@@ -433,7 +420,7 @@ ospf_rx_hook(sock *sk, int size)
#ifdef OSPFv2
/* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
struct ospf_neighbor *n;
- if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
+ if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
n = find_neigh_by_ip(ifa, sk->faddr);
else
n = find_neigh(ifa, rid);
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 5469bdcf..953a679a 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -1341,12 +1341,13 @@ static inline int
match_rtlink(struct ospf_iface *ifa, struct ospf_lsa_rt_link *rtl)
{
#ifdef OSPFv2
- return (ifa->type == OSPF_IT_PTP) && (ifa->cost == rtl->metric) &&
+ return ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) &&
+ (ifa->cost == rtl->metric) &&
(((ifa->addr->flags & IA_UNNUMBERED) ? ifa->iface->index :
ipa_to_u32(ifa->addr->ip)) == rtl->data);
#else /* OSPFv3 */
- return (ifa->type == OSPF_IT_PTP) && (ifa->cost == rtl->metric) &&
- (ifa->iface->index == rtl->lif);
+ return ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) &&
+ (ifa->cost == rtl->metric) && (ifa->iface->index == rtl->lif);
#endif
}
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index bb608498..dc6cd1dc 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -241,24 +241,26 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue;
+ /* RFC2328 - 12.4.1.1-4 */
switch (ifa->type)
{
- case OSPF_IT_PTP: /* RFC2328 - 12.4.1.1 */
- neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
- if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL))
- {
- ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- ln->type = LSART_PTP;
- ln->id = neigh->rid;
- ln->data = (ifa->addr->flags & IA_UNNUMBERED) ?
- ifa->iface->index : ipa_to_u32(ifa->addr->ip);
- ln->metric = ifa->cost;
- ln->padding = 0;
- i++;
- }
+ case OSPF_IT_PTP:
+ case OSPF_IT_PTMP:
+ WALK_LIST(neigh, ifa->neigh_list)
+ if (neigh->state == NEIGHBOR_FULL)
+ {
+ ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
+ ln->type = LSART_PTP;
+ ln->id = neigh->rid;
+ ln->data = (ifa->addr->flags & IA_UNNUMBERED) ?
+ ifa->iface->index : ipa_to_u32(ifa->addr->ip);
+ ln->metric = ifa->cost;
+ ln->padding = 0;
+ i++;
+ }
break;
- case OSPF_IT_BCAST: /* RFC2328 - 12.4.1.2 */
+ case OSPF_IT_BCAST:
case OSPF_IT_NBMA:
if (bcast_net_active(ifa))
{
@@ -273,7 +275,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
}
break;
- case OSPF_IT_VLINK: /* RFC2328 - 12.4.1.3 */
+ case OSPF_IT_VLINK:
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
{
@@ -300,7 +302,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
continue;
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- if (ifa->state == OSPF_IS_LOOP)
+ if ((ifa->state == OSPF_IS_LOOP) || (ifa->type == OSPF_IT_PTMP))
{
/* Host stub entry */
ln->type = LSART_STUB;
@@ -398,9 +400,10 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
switch (ifa->type)
{
case OSPF_IT_PTP:
- neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
- if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL))
- add_lsa_rt_link(po, ifa, LSART_PTP, neigh->iface_id, neigh->rid);
+ case OSPF_IT_PTMP:
+ WALK_LIST(neigh, ifa->neigh_list)
+ if (neigh->state == NEIGHBOR_FULL)
+ add_lsa_rt_link(po, ifa, LSART_PTP, neigh->iface_id, neigh->rid);
break;
case OSPF_IT_BCAST:
@@ -1202,7 +1205,7 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
configured_stubnet(oa, a))
continue;
- if (ifa->state == OSPF_IS_LOOP)
+ if ((ifa->state == OSPF_IS_LOOP) || (ifa->type == OSPF_IT_PTMP))
lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
else
lsa_put_prefix(po, a->prefix, a->pxlen, ifa->cost);