Commit 919f5411 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Implements Point-to-MultiPoint interface type for OSPF.

parent 39847cda
......@@ -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>
......
......@@ -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; }
......
......@@ -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",
......
......@@ -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;
......@@ -119,16 +134,6 @@ ospf_sk_open(struct ospf_iface *ifa)
return 0;
}
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)
{
......@@ -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);
......
......@@ -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_ */
......@@ -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()");
}
}
}
......
......@@ -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,
......
......@@ -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_ */
......@@ -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",
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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
}
......