diff options
-rw-r--r-- | doc/bird.sgml | 58 | ||||
-rw-r--r-- | proto/ospf/config.Y | 10 | ||||
-rw-r--r-- | proto/ospf/hello.c | 134 | ||||
-rw-r--r-- | proto/ospf/iface.c | 99 | ||||
-rw-r--r-- | proto/ospf/iface.h | 5 | ||||
-rw-r--r-- | proto/ospf/lsupd.c | 21 | ||||
-rw-r--r-- | proto/ospf/neighbor.c | 29 | ||||
-rw-r--r-- | proto/ospf/neighbor.h | 2 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 28 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 10 | ||||
-rw-r--r-- | proto/ospf/packet.c | 15 | ||||
-rw-r--r-- | proto/ospf/rt.c | 7 | ||||
-rw-r--r-- | proto/ospf/topology.c | 43 |
13 files changed, 255 insertions, 206 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index c7816f0..5d9c7bd 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 <name> { dead count <num>; dead <num>; rx buffer [normal|large|<num>]; - type [broadcast|nonbroadcast|pointopoint]; + type [broadcast|bcast|pointopoint|ptp| + nonbroadcast|nbma|pointomultipoint|ptmp]; strict nonbroadcast <switch>; check link <switch>; ecmp weight <num>; @@ -1688,23 +1689,43 @@ protocol ospf <name> { 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 <name> { 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 59e1fbe..321bd8d 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 216dc72..47b84a4 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 8b21f94..05442df 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 38a8148..f9631eb 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 fb757d0..06b62ae 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 05f024a..98c9de5 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 5612eca..dcaa12d 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 19e68e2..e10a405 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 2ef0180..e260dc0 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 bfc17d7..e8ebafd 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 5469bdc..953a679 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 bb60849..dc6cd1d 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); |