Implements Point-to-MultiPoint interface type for OSPF.

This commit is contained in:
Ondrej Zajicek 2010-12-24 18:08:07 +01:00
parent 39847cda73
commit 919f5411c4
13 changed files with 253 additions and 204 deletions

View file

@ -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>interface "*" { type broadcast; };</cf> - start the protocol on all interfaces with
<cf>type broadcast</cf> option. <cf>type broadcast</cf> option.
<cf>interface "eth1", "eth4", "eth5" { type pointopoint; };</cf> - start the protocol <cf>interface "eth1", "eth4", "eth5" { type ptp; };</cf> - start the protocol
on enumerated interfaces with <cf>type pointopoint</cf> option. 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 <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 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 count &lt;num&gt;;
dead &lt;num&gt;; dead &lt;num&gt;;
rx buffer [normal|large|&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;; strict nonbroadcast &lt;switch&gt;;
check link &lt;switch&gt;; check link &lt;switch&gt;;
ecmp weight &lt;num&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) be bigger than maximal size of any packets. Value NORMAL (default)
means 2*MTU, value LARGE means maximal allowed packet - 65535. means 2*MTU, value LARGE means maximal allowed packet - 65535.
<tag>type broadcast</tag> <tag>type broadcast|bcast</tag>
BIRD detects a type of a connected network automatically, but sometimes it's BIRD detects a type of a connected network automatically, but
convenient to force use of a different type manually. sometimes it's convenient to force use of a different type
On broadcast networks, flooding and Hello messages are sent using multicasts manually. On broadcast networks (like ethernet), flooding
(a single packet for all the neighbors). 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</tag> <tag>type pointopoint|ptp</tag>
Point-to-point networks connect just 2 routers together. No election Point-to-point networks connect just 2 routers together. No
is performed there which reduces the number of messages sent. 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</tag> <tag>type nonbroadcast|nbma</tag>
On nonbroadcast networks, the packets are sent to each neighbor On NBMA networks, the packets are sent to each neighbor
separately because of lack of multicast capabilities. 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> <tag>strict nonbroadcast <M>switch</M></tag>
If set, don't send hello to any undefined neighbor. This switch 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> <tag>check link <M>switch</M></tag>
If set, a hardware link state (reported by OS) is taken into 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. See <ref id="dsc-pass" name="password"> common option for detailed description.
<tag>neighbors { <m/set/ } </tag> <tag>neighbors { <m/set/ } </tag>
A set of neighbors to which Hello messages on nonbroadcast networks A set of neighbors to which Hello messages on NBMA or PtMP
are to be sent. Some of them could be marked as eligible. networks are to be sent. For NBMA networks, some of them
could be marked as eligible.
</descrip> </descrip>

View file

@ -46,8 +46,9 @@ finish_iface_config(struct ospf_iface_patt *ip)
CF_DECLS CF_DECLS
CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID) CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
CF_KEYWORDS(BROADCAST, NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT) CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE) 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(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY) 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 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"); } | 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 BROADCAST { OSPF_PATT->type = OSPF_IT_BCAST ; }
| TYPE BCAST { OSPF_PATT->type = OSPF_IT_BCAST ; }
| TYPE NONBROADCAST { OSPF_PATT->type = OSPF_IT_NBMA ; } | 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 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 ; } | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
| STUB bool { OSPF_PATT->stub = $2 ; } | STUB bool { OSPF_PATT->stub = $2 ; }
| CHECK LINK bool { OSPF_PATT->check_link = $3; } | CHECK LINK bool { OSPF_PATT->check_link = $3; }

View file

@ -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_ospf *po = ifa->oa->po;
struct proto *p = &po->proto; struct proto *p = &po->proto;
char *beg = "OSPF: Bad HELLO packet from "; char *beg = "OSPF: Bad HELLO packet from ";
unsigned int size, i, twoway, eligible, peers; unsigned int size, i, twoway, peers;
u32 tmp; u32 tmp;
u32 *pnrid; u32 *pnrid;
@ -103,37 +103,30 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
if (!n) if (!n)
{ {
if ((ifa->type == OSPF_IT_NBMA)) if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
{ {
struct nbma_node *nn; struct nbma_node *nn = find_nbma_node(ifa, faddr);
int found = 0;
WALK_LIST(nn, ifa->nbma_list) if (!nn && ifa->strictnbma)
{
if (ipa_equal(faddr, nn->ip))
{
found = 1;
break;
}
}
if ((found == 0) && (ifa->strictnbma))
{ {
log(L_WARN "Ignoring new neighbor: %I on %s", faddr, log(L_WARN "Ignoring new neighbor: %I on %s", faddr,
ifa->iface->name); ifa->iface->name);
return; return;
} }
if (found)
{ if (nn && (ifa->type == OSPF_IT_NBMA) &&
eligible = nn->eligible; (((ps->priority == 0) && nn->eligible) ||
if (((ps->priority == 0) && eligible) ((ps->priority > 0) && !nn->eligible)))
|| ((ps->priority > 0) && (eligible == 0)))
{ {
log(L_ERR "Eligibility mismatch for neighbor: %I on %s", log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
faddr, ifa->iface->name); faddr, ifa->iface->name);
return; return;
} }
if (nn)
nn->found = 1;
} }
}
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr,
ifa->iface->name); ifa->iface->name);
@ -239,7 +232,7 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
struct ospf_neighbor *neigh, *n1; struct ospf_neighbor *neigh, *n1;
u16 length; u16 length;
u32 *pp; u32 *pp;
int i, send; int i;
struct nbma_node *nb; struct nbma_node *nb;
if (timer == NULL) if (timer == NULL)
@ -311,53 +304,56 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
switch(ifa->type) switch(ifa->type)
{ {
case OSPF_IT_BCAST:
case OSPF_IT_PTP:
ospf_send_to(ifa, AllSPFRouters);
break;
case OSPF_IT_NBMA: case OSPF_IT_NBMA:
if (timer == NULL) /* Response to received hello */ if (timer == NULL) /* Response to received hello */
{ {
ospf_send_to(ifa, dirn->ip); 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; break;
} }
}
if ((poll == 1) && (send)) int to_all = ifa->state > OSPF_IS_DROTHER;
int me_elig = ifa->priority > 0;
if (poll) /* Poll timer */
{ {
if (toall || (meeli && nb->eligible)) WALK_LIST(nb, ifa->nbma_list)
if (!nb->found && (to_all || (me_elig && nb->eligible)))
ospf_send_to(ifa, nb->ip); ospf_send_to(ifa, nb->ip);
} }
} else /* Hello timer */
if (poll == 0)
{ {
WALK_LIST(n1, ifa->neigh_list) WALK_LIST(n1, ifa->neigh_list)
{ if (to_all || (me_elig && (n1->priority > 0)) ||
if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid))
(meeli && (n1->priority > 0)))
ospf_send_to(ifa, n1->ip); ospf_send_to(ifa, n1->ip);
} }
}
}
break; 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: case OSPF_IT_VLINK:
ospf_send_to(ifa, ifa->vip); ospf_send_to(ifa, ifa->vip);
break; break;
default: default:
ospf_send_to(ifa, AllSPFRouters); bug("Bug in ospf_hello_send()");
} }
OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s", OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s",

View file

@ -8,7 +8,7 @@
#include "ospf.h" #include "ospf.h"
char *ospf_is[] = { "down", "loop", "waiting", "point-to-point", "drother", char *ospf_is[] = { "down", "loop", "waiting", "ptp", "drother",
"backup", "dr" "backup", "dr"
}; };
@ -16,7 +16,7 @@ char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen",
"neighbor change", "loop indicated", "unloop indicated", "interface down" "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 static void
poll_timer_hook(timer * timer) 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 static int
ospf_sk_open(struct ospf_iface *ifa) ospf_sk_open(struct ospf_iface *ifa, int multicast)
{ {
sock *sk = sk_new(ifa->pool); sock *sk = sk_new(ifa->pool);
sk->type = SK_IP; sk->type = SK_IP;
@ -106,11 +116,16 @@ ospf_sk_open(struct ospf_iface *ifa)
*/ */
sk->saddr = ifa->addr->ip; sk->saddr = ifa->addr->ip;
if (multicast)
{
if (sk_setup_multicast(sk) < 0) if (sk_setup_multicast(sk) < 0)
goto err; goto err;
if (sk_join_group(sk, AllSPFRouters) < 0)
goto err;
}
ifa->sk = sk; ifa->sk = sk;
ifa->sk_spf = 0;
ifa->sk_dr = 0; ifa->sk_dr = 0;
return 1; return 1;
@ -119,16 +134,6 @@ ospf_sk_open(struct ospf_iface *ifa)
return 0; 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 static inline void
ospf_sk_join_dr(struct ospf_iface *ifa) 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); sk_join_group(ifa->sk, AllDRouters);
ifa->sk_dr = 1; 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 static inline void
ospf_sk_leave_dr(struct ospf_iface *ifa) 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) if (ifa->state <= OSPF_IS_LOOP)
{ {
/* Now, nothing should be adjacent */ /* 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); ospf_iface_chstate(ifa, OSPF_IS_PTP);
} }
@ -355,11 +349,11 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
} }
u8 static u8
ospf_iface_clasify(struct iface *ifa, struct ifa *addr) ospf_iface_classify(struct iface *ifa, struct ifa *addr)
{ {
if (ipa_nonzero(addr->opposite)) 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 ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
(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_ospf *po = ifa->oa->po;
struct proto *p = &po->proto; struct proto *p = &po->proto;
if (ospf_sk_open(ifa)) int mc = (ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP);
{ if (! ospf_sk_open(ifa, mc))
if (ifa->type != OSPF_IT_NBMA)
ospf_sk_join_spf(ifa);
}
else
{ {
log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->iface->name); log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->iface->name);
ifa->ioprob = OSPF_I_SK; ifa->ioprob = OSPF_I_SK;
@ -448,7 +438,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
#endif #endif
if (ip->type == OSPF_IT_UNDEF) if (ip->type == OSPF_IT_UNDEF)
ifa->type = ospf_iface_clasify(iface, addr); ifa->type = ospf_iface_classify(iface, addr);
else else
ifa->type = ip->type; 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)) if ((addr->pxlen == MAX_PREFIX_LENGTH) && ipa_zero(addr->opposite))
ifa->stub = 1; ifa->stub = 1;
/* Check validity of interface type */
int old_type = ifa->type;
#ifdef OSPFv2 #ifdef OSPFv2
if ((ifa->type != OSPF_IT_PTP) && (ifa->type != OSPF_IT_VLINK) && if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_UNNUMBERED))
(addr->flags & IA_UNNUMBERED))
{
log(L_WARN "%s: Missing proper IP prefix on interface %s, forcing point-to-point mode",
p->name, iface->name);
ifa->type = OSPF_IT_PTP; ifa->type = OSPF_IT_PTP;
}
if ((ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_UNNUMBERED))
ifa->type = OSPF_IT_PTMP;
#endif #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->neigh_list);
init_list(&ifa->nbma_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 = mb_alloc(pool, sizeof(struct nbma_node));
nbma->ip = nb->ip; nbma->ip = nb->ip;
nbma->eligible = nb->eligible; nbma->eligible = nb->eligible;
nbma->found = 0;
add_tail(&ifa->nbma_list, NODE nbma); add_tail(&ifa->nbma_list, NODE nbma);
} }
@ -766,10 +769,12 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
void void
ospf_iface_info(struct ospf_iface *ifa) 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) if (ifa->type == OSPF_IT_VLINK)
{ {
cli_msg(-1015, "Virtual link to %R:", ifa->vid); cli_msg(-1015, "Virtual link to %R:", ifa->vid);

View file

@ -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_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa);
void ospf_set_rxbuf_size(struct ospf_iface *ifa, u32 rxbuf); 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_ */ #endif /* _BIRD_OSPF_IFACE_H_ */

View file

@ -304,6 +304,13 @@ ospf_lsupd_flood(struct proto_ospf *po,
switch (ifa->type) 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: case OSPF_IT_NBMA:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR)) if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
@ -311,16 +318,20 @@ ospf_lsupd_flood(struct proto_ospf *po,
ospf_send_to_bdr(ifa); ospf_send_to_bdr(ifa);
break; 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: case OSPF_IT_VLINK:
ospf_send_to(ifa, ifa->vip); ospf_send_to(ifa, ifa->vip);
break; break;
default: default:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) || bug("Bug in ospf_lsupd_flood()");
(ifa->type == OSPF_IT_PTP))
ospf_send_to(ifa, AllSPFRouters);
else
ospf_send_to(ifa, AllDRouters);
} }
} }
} }

View file

@ -276,6 +276,7 @@ can_do_adj(struct ospf_neighbor *n)
switch (ifa->type) switch (ifa->type)
{ {
case OSPF_IT_PTP: case OSPF_IT_PTP:
case OSPF_IT_PTMP:
case OSPF_IT_VLINK: case OSPF_IT_VLINK:
i = 1; i = 1;
break; break;
@ -531,8 +532,18 @@ struct ospf_neighbor *
find_neigh(struct ospf_iface *ifa, u32 rid) find_neigh(struct ospf_iface *ifa, u32 rid)
{ {
struct ospf_neighbor *n; 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) 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 n;
return NULL; return NULL;
} }
@ -567,6 +578,13 @@ ospf_neigh_remove(struct ospf_neighbor *n)
struct ospf_iface *ifa = n->ifa; struct ospf_iface *ifa = n->ifa;
struct proto *p = &ifa->oa->po->proto; 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)); s_get(&(n->dbsi));
neigh_chstate(n, NEIGHBOR_DOWN); neigh_chstate(n, NEIGHBOR_DOWN);
rem_node(NODE n); rem_node(NODE n);
@ -596,9 +614,10 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
if (n->rid == ifa->drid) if (n->rid == ifa->drid)
pos = "dr "; pos = "dr ";
if (n->rid == ifa->bdrid) else if (n->rid == ifa->bdrid)
pos = "bdr "; 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 "; pos = "ptp ";
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority, cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,

View file

@ -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 ospf_neigh_sm(struct ospf_neighbor *n, int event);
void bdr_election(struct ospf_iface *ifa); void bdr_election(struct ospf_iface *ifa);
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid); 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); struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
void ospf_neigh_remove(struct ospf_neighbor *n); void ospf_neigh_remove(struct ospf_neighbor *n);
void ospf_sh_neigh_info(struct ospf_neighbor *n); void ospf_sh_neigh_info(struct ospf_neighbor *n);
#endif /* _BIRD_OSPF_NEIGHBOR_H_ */ #endif /* _BIRD_OSPF_NEIGHBOR_H_ */

View file

@ -649,7 +649,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
struct ospf_iface *ifa; struct ospf_iface *ifa;
struct nbma_node *nb1, *nb2, *nbnx; struct nbma_node *nb1, *nb2, *nbnx;
struct ospf_area *oa = NULL; struct ospf_area *oa = NULL;
int found, olddead, newdead; int olddead, newdead;
if (po->rfc1583 != new->rfc1583) if (po->rfc1583 != new->rfc1583)
return 0; return 0;
@ -881,19 +881,17 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
/* First remove old */ /* First remove old */
WALK_LIST_DELSAFE(nb1, nbnx, ifa->nbma_list) WALK_LIST_DELSAFE(nb1, nbnx, ifa->nbma_list)
{ {
found = 0; nb2 = find_nbma_node_in(&newip->nbma_list, nb1->ip);
WALK_LIST(nb2, newip->nbma_list) if (nb2)
if (ipa_equal(nb1->ip, nb2->ip))
{ {
found = 1;
if (nb1->eligible != nb2->eligible) 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); nb1->ip, ifa->iface->name);
break;
} }
}
if (!found) else
{ {
OSPF_TRACE(D_EVENTS, OSPF_TRACE(D_EVENTS,
"Removing NBMA neighbor %I on interface %s", "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)) if (!ipa_in_net(nb2->ip, ifa->addr->prefix, ifa->addr->pxlen))
continue; continue;
found = 0; if (find_nbma_node(ifa, nb2->ip) == NULL)
WALK_LIST(nb1, ifa->nbma_list)
if (ipa_equal(nb1->ip, nb2->ip))
{
found = 1;
break;
}
if (!found)
{ {
nb1 = mb_alloc(ifa->pool, sizeof(struct nbma_node)); nb1 = mb_alloc(ifa->pool, sizeof(struct nbma_node));
nb1->ip = nb2->ip; nb1->ip = nb2->ip;
nb1->eligible = nb2->eligible; nb1->eligible = nb2->eligible;
nb1->found = !!find_neigh_by_ip(ifa, nb1->ip);
add_tail(&ifa->nbma_list, NODE nb1); add_tail(&ifa->nbma_list, NODE nb1);
OSPF_TRACE(D_EVENTS, OSPF_TRACE(D_EVENTS,
"Adding NBMA neighbor %I on interface %s", "Adding NBMA neighbor %I on interface %s",

View file

@ -90,7 +90,8 @@ struct nbma_node
{ {
node n; node n;
ip_addr ip; ip_addr ip;
int eligible; byte eligible;
byte found;
}; };
struct area_net_config struct area_net_config
@ -205,8 +206,9 @@ struct ospf_iface
#define OSPF_IT_BCAST 0 #define OSPF_IT_BCAST 0
#define OSPF_IT_NBMA 1 #define OSPF_IT_NBMA 1
#define OSPF_IT_PTP 2 #define OSPF_IT_PTP 2
#define OSPF_IT_VLINK 3 #define OSPF_IT_PTMP 3
#define OSPF_IT_UNDEF 4 #define OSPF_IT_VLINK 4
#define OSPF_IT_UNDEF 5
u8 strictnbma; /* Can I talk with unknown neighbors? */ u8 strictnbma; /* Can I talk with unknown neighbors? */
u8 stub; /* Inactive interface */ u8 stub; /* Inactive interface */
u8 state; /* Interface state machine */ u8 state; /* Interface state machine */
@ -245,7 +247,7 @@ struct ospf_iface
#define OSPF_I_OK 0 /* Everything OK */ #define OSPF_I_OK 0 /* Everything OK */
#define OSPF_I_SK 1 /* Socket open failed */ #define OSPF_I_SK 1 /* Socket open failed */
#define OSPF_I_LL 2 /* Missing link-local address (OSPFv3) */ #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 */ u8 sk_dr; /* Socket is a member of DRouters group */
u16 rxbuf; /* Buffer size */ u16 rxbuf; /* Buffer size */
u8 check_link; /* Whether iface link change is used */ u8 check_link; /* Whether iface link change is used */

View file

@ -240,19 +240,6 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
#endif #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 * ospf_rx_hook
@ -433,7 +420,7 @@ ospf_rx_hook(sock *sk, int size)
#ifdef OSPFv2 #ifdef OSPFv2
/* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */ /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
struct ospf_neighbor *n; 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); n = find_neigh_by_ip(ifa, sk->faddr);
else else
n = find_neigh(ifa, rid); n = find_neigh(ifa, rid);

View file

@ -1341,12 +1341,13 @@ static inline int
match_rtlink(struct ospf_iface *ifa, struct ospf_lsa_rt_link *rtl) match_rtlink(struct ospf_iface *ifa, struct ospf_lsa_rt_link *rtl)
{ {
#ifdef OSPFv2 #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 : (((ifa->addr->flags & IA_UNNUMBERED) ? ifa->iface->index :
ipa_to_u32(ifa->addr->ip)) == rtl->data); ipa_to_u32(ifa->addr->ip)) == rtl->data);
#else /* OSPFv3 */ #else /* OSPFv3 */
return (ifa->type == OSPF_IT_PTP) && (ifa->cost == rtl->metric) && return ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) &&
(ifa->iface->index == rtl->lif); (ifa->cost == rtl->metric) && (ifa->iface->index == rtl->lif);
#endif #endif
} }

View file

@ -241,11 +241,13 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN)) if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
continue; continue;
/* RFC2328 - 12.4.1.1-4 */
switch (ifa->type) switch (ifa->type)
{ {
case OSPF_IT_PTP: /* RFC2328 - 12.4.1.1 */ case OSPF_IT_PTP:
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list); case OSPF_IT_PTMP:
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL)) WALK_LIST(neigh, ifa->neigh_list)
if (neigh->state == NEIGHBOR_FULL)
{ {
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link)); ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
ln->type = LSART_PTP; ln->type = LSART_PTP;
@ -258,7 +260,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
} }
break; break;
case OSPF_IT_BCAST: /* RFC2328 - 12.4.1.2 */ case OSPF_IT_BCAST:
case OSPF_IT_NBMA: case OSPF_IT_NBMA:
if (bcast_net_active(ifa)) if (bcast_net_active(ifa))
{ {
@ -273,7 +275,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
} }
break; break;
case OSPF_IT_VLINK: /* RFC2328 - 12.4.1.3 */ case OSPF_IT_VLINK:
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list); neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff)) 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; continue;
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link)); 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 */ /* Host stub entry */
ln->type = LSART_STUB; ln->type = LSART_STUB;
@ -398,8 +400,9 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
switch (ifa->type) switch (ifa->type)
{ {
case OSPF_IT_PTP: case OSPF_IT_PTP:
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list); case OSPF_IT_PTMP:
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL)) WALK_LIST(neigh, ifa->neigh_list)
if (neigh->state == NEIGHBOR_FULL)
add_lsa_rt_link(po, ifa, LSART_PTP, neigh->iface_id, neigh->rid); add_lsa_rt_link(po, ifa, LSART_PTP, neigh->iface_id, neigh->rid);
break; break;
@ -1202,7 +1205,7 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
configured_stubnet(oa, a)) configured_stubnet(oa, a))
continue; 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); lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
else else
lsa_put_prefix(po, a->prefix, a->pxlen, ifa->cost); lsa_put_prefix(po, a->prefix, a->pxlen, ifa->cost);