diff options
author | Ondrej Filip <feela@network.cz> | 2004-07-14 23:46:20 +0200 |
---|---|---|
committer | Ondrej Filip <feela@network.cz> | 2004-07-14 23:46:20 +0200 |
commit | 3b16080c97a2d89c90f7df7a8fda0401ec9abe42 (patch) | |
tree | ef885699eaa72453b99f40dba181112d7e9540b7 /proto/ospf | |
parent | a417ad13a117d2458702cbec4aa418ba99981611 (diff) | |
download | bird-3b16080c97a2d89c90f7df7a8fda0401ec9abe42.tar bird-3b16080c97a2d89c90f7df7a8fda0401ec9abe42.zip |
Multiple OSPF areas can be attached.
Origination of summary LSA works.
Routing table calculation works.
Virtual links works.
Well, I hope, OSPF is fully compatible with RFC2328!!!!
Diffstat (limited to 'proto/ospf')
-rw-r--r-- | proto/ospf/config.Y | 21 | ||||
-rw-r--r-- | proto/ospf/hello.c | 14 | ||||
-rw-r--r-- | proto/ospf/iface.c | 219 | ||||
-rw-r--r-- | proto/ospf/lsalib.c | 4 | ||||
-rw-r--r-- | proto/ospf/lsupd.c | 25 | ||||
-rw-r--r-- | proto/ospf/neighbor.c | 18 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 63 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 7 | ||||
-rw-r--r-- | proto/ospf/packet.c | 25 | ||||
-rw-r--r-- | proto/ospf/rt.c | 88 | ||||
-rw-r--r-- | proto/ospf/topology.c | 65 |
11 files changed, 314 insertions, 235 deletions
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 87a97bc..bd3a2e5 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -58,9 +58,9 @@ ospf_area_start: AREA idval '{' { this_area = cfg_allocz(sizeof(struct ospf_area_config)); add_tail(&OSPF_CFG->area_list, NODE this_area); this_area->areaid = $2; - this_area->tick = DEFAULT_AREATICK; this_area->stub = 0; init_list(&this_area->patt_list); + init_list(&this_area->vlink_list); init_list(&this_area->net_list); } ; @@ -75,13 +75,14 @@ ospf_area_opts: ospf_area_item: STUB COST expr { this_area->stub = $3 ; if($3<=0) cf_error("Stub cost must be greater than zero"); } - | TICK expr { this_area->tick = $2 ; if($2<=0) cf_error("Tick must be greater than zero"); } | NETWORKS '{' pref_list '}' | INTERFACE ospf_iface_list - | ospf_vlink '}' + | ospf_vlink ; -ospf_vlink: ospf_vlink_start ospf_vlink_opts +ospf_vlink: + ospf_vlink_start '{' ospf_vlink_opts '}' + | ospf_vlink_start ; ospf_vlink_opts: @@ -90,8 +91,7 @@ ospf_vlink_opts: ; ospf_vlink_item: - HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); } - | POLL expr { OSPF_PATT->pollint = $2 ; if ($2<=0) cf_error("Poll int must be greater than zero"); } + | HELLO expr { OSPF_PATT->helloint = $2 ; if (($2<=0) || ($2>65535)) cf_error("Hello interval must be in range 1-65535"); } | RETRANSMIT expr { OSPF_PATT->rxmtint = $2 ; if ($2<=0) cf_error("Retransmit int must be greater than zero"); } | TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); } | WAIT expr { OSPF_PATT->waitint = $2 ; } @@ -102,19 +102,21 @@ ospf_vlink_item: | password_list {OSPF_PATT->passwords = $1; } ; -ospf_vlink_start: VIRTUAL LINK '{' +ospf_vlink_start: VIRTUAL LINK idval { + log("Vlink start"); if (this_area->areaid == 0) cf_error("Virtual link cannot be in backbone"); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); - add_tail(&this_area->patt_list, NODE this_ipatt); + add_tail(&this_area->vlink_list, NODE this_ipatt); + OSPF_PATT->vid = $3; OSPF_PATT->cost = COST_D; OSPF_PATT->helloint = HELLOINT_D; - OSPF_PATT->pollint = POLLINT_D; OSPF_PATT->rxmtint = RXMTINT_D; OSPF_PATT->inftransdelay = INFTRANSDELAY_D; OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D; OSPF_PATT->deadc = DEADC_D; OSPF_PATT->type = OSPF_IT_VLINK; + init_list(&OSPF_PATT->nbma_list); OSPF_PATT->autype = OSPF_AUTH_NONE; } ; @@ -198,6 +200,7 @@ ipa_ne: IPA ELIGIBLE ';' ospf_iface_start: { + log("Iface start"); this_ipatt = cfg_allocz(sizeof(struct ospf_iface_patt)); add_tail(&this_area->patt_list, NODE this_ipatt); OSPF_PATT->cost = COST_D; diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 7820cf7..350bad7 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -19,12 +19,13 @@ ospf_hello_receive(struct ospf_hello_packet *ps, struct proto *p = (struct proto *) ifa->proto; unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers; - OSPF_TRACE(D_PACKETS, "Received hello from %I via %s", faddr, - ifa->iface->name); + OSPF_TRACE(D_PACKETS, "Received hello from %I via %s%s", faddr, + (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name); mask = ps->netmask; ipa_ntoh(mask); - if ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen) + if ((ifa->type != OSPF_IT_VLINK) && + ((unsigned) ipa_mklen(mask) != ifa->iface->addr->pxlen)) { log(L_ERR "%s%I%sbad netmask %I.", beg, faddr, rec, mask); return; @@ -151,7 +152,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps, ospf_iface_sm(ifa, ISM_NEICH); } - if (ifa->type != OSPF_IT_NBMA) + if (ifa->type == OSPF_IT_NBMA) { if ((ifa->priority == 0) && (n->priority > 0)) ospf_hello_send(NULL, 0, n); @@ -171,7 +172,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn) u32 *pp; int i, send; struct nbma_node *nb; - if (timer == NULL) ifa = dirn->ifa; else @@ -204,6 +204,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn) pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen); ipa_hton(pkt->netmask); + if (ifa->type == OSPF_IT_VLINK) pkt->netmask = IPA_NONE; pkt->helloint = ntohs(ifa->helloint); pkt->options = ifa->oa->opt.byte; pkt->priority = ifa->priority; @@ -280,5 +281,6 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn) default: ospf_send_to(ifa->hello_sk, IPA_NONE, ifa); } - OSPF_TRACE(D_PACKETS, "Hello sent via %s", ifa->iface->name); + OSPF_TRACE(D_PACKETS, "Hello sent via %s%s", + (ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name); } diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 62b8899..5a10cde 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -21,6 +21,7 @@ char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" }; static void poll_timer_hook(timer * timer) { + log("POLL!"); ospf_hello_send(timer, 1, NULL); } @@ -40,6 +41,38 @@ wait_timer_hook(timer * timer) ospf_iface_sm(ifa, ISM_WAITF); } +static sock * +ospf_open_ip_socket(struct ospf_iface *ifa) +{ + sock *ipsk; + struct proto *p; + + p = (struct proto *) (ifa->proto); + + ipsk = sk_new(p->pool); + ipsk->type = SK_IP; + ipsk->dport = OSPF_PROTO; + ipsk->saddr = ifa->iface->addr->ip; + ipsk->tos = IP_PREC_INTERNET_CONTROL; + ipsk->ttl = 1; + if (ifa->type == OSPF_IT_VLINK) + ipsk->ttl = 255; + ipsk->rx_hook = ospf_rx_hook; + ipsk->tx_hook = ospf_tx_hook; + ipsk->err_hook = ospf_err_hook; + ipsk->iface = ifa->iface; + ipsk->rbsize = ifa->iface->mtu; + ipsk->tbsize = ifa->iface->mtu; + ipsk->data = (void *) ifa; + if (sk_open(ipsk) != 0) + { + DBG("%s: SK_OPEN: ip open failed.\n", p->name); + return (NULL); + } + DBG("%s: SK_OPEN: ip opened.\n", p->name); + return (ipsk); +} + /** * ospf_iface_chstate - handle changes of interface state @@ -55,58 +88,71 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state) { struct proto_ospf *po = ifa->proto; struct proto *p = &po->proto; - u8 oldstate; + u8 oldstate = ifa->state; - if (ifa->state != state) + if (oldstate != state) { - OSPF_TRACE(D_EVENTS, - "Changing state of iface: %s from \"%s\" into \"%s\".", - ifa->iface->name, ospf_is[ifa->state], ospf_is[state]); - oldstate = ifa->state; ifa->state = state; - if (ifa->iface->flags & IF_MULTICAST) + + if (ifa->type == OSPF_IT_VLINK) { - if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)) + OSPF_TRACE(D_EVENTS, + "Changing state of virtual link %I from \"%s\" into \"%s\".", + ifa->vid, ospf_is[oldstate], ospf_is[state]); + if (state == OSPF_IS_PTP) { - if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA)) + ifa->ip_sk = ospf_open_ip_socket(ifa); + } + } + else + { + OSPF_TRACE(D_EVENTS, + "Changing state of iface: %s from \"%s\" into \"%s\".", + ifa->iface->name, ospf_is[oldstate], ospf_is[state]); + if (ifa->iface->flags & IF_MULTICAST) + { + if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)) { - DBG("%s: Adding new multicast socket for (B)DR\n", p->name); - ifa->dr_sk = sk_new(p->pool); - ifa->dr_sk->type = SK_IP_MC; - ifa->dr_sk->sport = 0; - ifa->dr_sk->dport = OSPF_PROTO; - ifa->dr_sk->saddr = AllDRouters; - ifa->dr_sk->daddr = AllDRouters; - ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL; - ifa->dr_sk->ttl = 1; - ifa->dr_sk->rx_hook = ospf_rx_hook; - ifa->dr_sk->tx_hook = ospf_tx_hook; - ifa->dr_sk->err_hook = ospf_err_hook; - ifa->dr_sk->iface = ifa->iface; - ifa->dr_sk->rbsize = ifa->iface->mtu; - ifa->dr_sk->tbsize = ifa->iface->mtu; - ifa->dr_sk->data = (void *) ifa; - if (sk_open(ifa->dr_sk) != 0) + if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA)) { - DBG("%s: SK_OPEN: new? mc open failed.\n", p->name); + DBG("%s: Adding new multicast socket for (B)DR\n", p->name); + ifa->dr_sk = sk_new(p->pool); + ifa->dr_sk->type = SK_IP_MC; + ifa->dr_sk->sport = 0; + ifa->dr_sk->dport = OSPF_PROTO; + ifa->dr_sk->saddr = AllDRouters; + ifa->dr_sk->daddr = AllDRouters; + ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL; + ifa->dr_sk->ttl = 1; + ifa->dr_sk->rx_hook = ospf_rx_hook; + ifa->dr_sk->tx_hook = ospf_tx_hook; + ifa->dr_sk->err_hook = ospf_err_hook; + ifa->dr_sk->iface = ifa->iface; + ifa->dr_sk->rbsize = ifa->iface->mtu; + ifa->dr_sk->tbsize = ifa->iface->mtu; + ifa->dr_sk->data = (void *) ifa; + if (sk_open(ifa->dr_sk) != 0) + { + DBG("%s: SK_OPEN: new? mc open failed.\n", p->name); + } } } - } - else - { - rfree(ifa->dr_sk); - ifa->dr_sk = NULL; - } - if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL)) - { - ifa->nlsa->lsa.age = LSA_MAXAGE; - if (state >= OSPF_IS_WAITING) + else { - ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa); + rfree(ifa->dr_sk); + ifa->dr_sk = NULL; + } + if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL)) + { + ifa->nlsa->lsa.age = LSA_MAXAGE; + if (state >= OSPF_IS_WAITING) + { + ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa); + } + if (can_flush_lsa(ifa->oa)) + flush_lsa(ifa->nlsa, ifa->oa); + ifa->nlsa = NULL; } - if (can_flush_lsa(ifa->oa)) - flush_lsa(ifa->nlsa, ifa->oa); - ifa->nlsa = NULL; } } } @@ -120,6 +166,16 @@ ospf_iface_down(struct ospf_iface *ifa) struct proto_ospf *po = ifa->proto; struct ospf_iface *iff; + /* First of all kill all the related vlinks */ + if (ifa->type != OSPF_IT_VLINK) + { + WALK_LIST(iff, po->iface_list) + { + if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface)) + ospf_iface_down(iff); + } + } + WALK_LIST_DELSAFE(n, nx, ifa->neigh_list) { OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip); @@ -129,7 +185,7 @@ ospf_iface_down(struct ospf_iface *ifa) rfree(ifa->dr_sk); rfree(ifa->ip_sk); - if(ifa->type == OSPF_IT_VLINK) + if (ifa->type == OSPF_IT_VLINK) { ifa->ip_sk = NULL; ifa->iface = NULL; @@ -144,7 +200,6 @@ ospf_iface_down(struct ospf_iface *ifa) rem_node(NODE ifa); mb_free(ifa); } - /* FIXME: Should I down related VLINK also? */ } /** @@ -168,13 +223,10 @@ ospf_iface_sm(struct ospf_iface *ifa, int event) if (ifa->state == OSPF_IS_DOWN) { /* Now, nothing should be adjacent */ - tm_start(ifa->hello_timer, ifa->helloint); - - if (ifa->poll_timer) - tm_start(ifa->poll_timer, ifa->pollint); - if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK)) + { ospf_iface_chstate(ifa, OSPF_IS_PTP); + } else { if (ifa->priority == 0) @@ -185,6 +237,12 @@ ospf_iface_sm(struct ospf_iface *ifa, int event) tm_start(ifa->wait_timer, ifa->waitint); } } + + tm_start(ifa->hello_timer, ifa->helloint); + + if (ifa->poll_timer) + tm_start(ifa->poll_timer, ifa->pollint); + hello_timer_hook(ifa->hello_timer); } schedule_rt_lsa(ifa->oa); @@ -257,37 +315,6 @@ ospf_open_mc_socket(struct ospf_iface *ifa) return (mcsk); } -static sock * -ospf_open_ip_socket(struct ospf_iface *ifa) -{ - sock *ipsk; - struct proto *p; - - p = (struct proto *) (ifa->proto); - - ipsk = sk_new(p->pool); - ipsk->type = SK_IP; - ipsk->dport = OSPF_PROTO; - ipsk->saddr = ifa->iface->addr->ip; - ipsk->tos = IP_PREC_INTERNET_CONTROL; - ipsk->ttl = 1; - if (ifa->type == OSPF_IT_VLINK) ipsk->ttl = 255; - ipsk->rx_hook = ospf_rx_hook; - ipsk->tx_hook = ospf_tx_hook; - ipsk->err_hook = ospf_err_hook; - ipsk->iface = ifa->iface; - ipsk->rbsize = ifa->iface->mtu; - ipsk->tbsize = ifa->iface->mtu; - ipsk->data = (void *) ifa; - if (sk_open(ipsk) != 0) - { - DBG("%s: SK_OPEN: ip open failed.\n", p->name); - return (NULL); - } - DBG("%s: SK_OPEN: ip opened.\n", p->name); - return (ipsk); -} - u8 ospf_iface_clasify(struct iface * ifa) { @@ -306,7 +333,7 @@ ospf_iface_find(struct proto_ospf *p, struct iface *what) { struct ospf_iface *i; - WALK_LIST(i, p->iface_list) if ((i)->iface == what) + WALK_LIST(i, p->iface_list) if ((i->iface == what) && (i->type != OSPF_IT_VLINK)) return i; return NULL; } @@ -350,7 +377,8 @@ ospf_iface_add(struct object_lock *lock) } void -ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip) +ospf_iface_new(struct proto_ospf *po, struct iface *iface, + struct ospf_area_config *ac, struct ospf_iface_patt *ip) { struct proto *p = &po->proto; struct ospf_iface *ifa; @@ -362,7 +390,6 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf ifa->proto = po; ifa->iface = iface; - ifa->an = ac->areaid; ifa->cost = ip->cost; ifa->rxmtint = ip->rxmtint; ifa->inftransdelay = ip->inftransdelay; @@ -383,6 +410,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf init_list(&ifa->neigh_list); init_list(&ifa->nbma_list); + WALK_LIST(nb, ip->nbma_list) { nbma = mb_alloc(p->pool, sizeof(struct nbma_node)); @@ -420,23 +448,26 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa); ifa->state = OSPF_IS_DOWN; + ifa->oa = NULL; WALK_LIST(oa, po->area_list) { - if (oa->areaid == ifa->an) + if (oa->areaid == ac->areaid) + { + ifa->oa = oa; break; + } } - if (EMPTY_LIST(po->area_list) || (oa->areaid != ifa->an)) /* New area */ + if (!ifa->oa) bug("Cannot add any area to accepted Interface"); else - ifa->oa = oa; if (ifa->type == OSPF_IT_VLINK) { ifa->oa = po->backbone; ifa->voa = oa; ifa->vid = ip->vid; - return; /* Don't lock, don't add sockets */ + return; /* Don't lock, don't add sockets */ } lock = olock_new(p->pool); @@ -536,9 +567,19 @@ ospf_iface_info(struct ospf_iface *ifa) if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0)) strict = ""; - cli_msg(-1015, "Interface \"%s\":", ifa->iface->name); - cli_msg(-1015, "\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid); - cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict); + if (ifa->type == OSPF_IT_VLINK) + { + cli_msg(-1015, "Virtual link to %I:", ifa->vid); + cli_msg(-1015, "\tTransit area: %I (%u)", ifa->voa->areaid, + ifa->voa->areaid); + } + else + { + cli_msg(-1015, "Interface \"%s\":", + (ifa->iface ? ifa->iface->name : "(none)")); + cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict); + cli_msg(-1015, "\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid); + } cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state], ifa->stub ? "(stub)" : ""); cli_msg(-1015, "\tPriority: %u", ifa->priority); diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index 7ea8304..b244c3f 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -55,8 +55,8 @@ ospf_age(struct ospf_area *oa) en->color = OUTSPF; en->dist = LSINFINITY; en->nhi = NULL; - en->nh = ipa_from_u32(0); - en->lb = ipa_from_u32(0); + en->nh = IPA_NONE; + en->lb = IPA_NONE; DBG("Infinitying Type: %u, Id: %I, Rt: %I\n", en->lsa.type, en->lsa.id, en->lsa.rt); } diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c index 44d35d9..51b38af 100644 --- a/proto/ospf/lsupd.c +++ b/proto/ospf/lsupd.c @@ -152,10 +152,10 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, struct ospf_packet *op; struct ospf_lsa_header *lh; - if (ifa->type == OSPF_IT_NBMA) + if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK)) sk = ifa->ip_sk; else - sk = ifa->hello_sk; /* FIXME is this true for PTP? */ + sk = ifa->hello_sk; pk = (struct ospf_lsupd_packet *) sk->tbuf; op = (struct ospf_packet *) sk->tbuf; @@ -192,16 +192,23 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, op->length = htons(len); OSPF_TRACE(D_PACKETS, "LS upd flooded via %s", ifa->iface->name); + DBG("ID=%I, AGE=%d, SEQ=%x", ntohl(lh->id), ntohs(lh->age), + ntohl(lh->sn)); - if (ifa->type == OSPF_IT_NBMA) + switch (ifa->type) { + case OSPF_IT_NBMA: if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR)) ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE); else ospf_send_to_bdr(sk, ifa); - } - else - { + break; + + case OSPF_IT_VLINK: + ospf_send_to(sk, ifa->vip, ifa); + break; + + default: if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) || (ifa->type == OSPF_IT_PTP)) ospf_send_to(sk, AllSPFRouters, ifa); @@ -243,6 +250,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l) if ((en = ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt, llsh->lsh.type)) == NULL) continue; /* Probably flushed LSA */ + /* FIXME This is a bug! I cannot flush LSA that is in lsrt */ DBG("Sending ID=%I, Type=%u, RT=%I Sn: 0x%x Age: %u\n", llsh->lsh.id, llsh->lsh.type, llsh->lsh.rt, en->lsa.sn, en->lsa.age); @@ -395,8 +403,9 @@ ospf_lsupd_receive(struct ospf_lsupd_packet *ps, { WALK_LIST(nifa, po->iface_list) { - if (ipa_compare(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)) == - 0) + if (!nifa->iface) + continue; + if (ipa_equal(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id))) { self = 1; break; diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index e9ef476..869db2b 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -122,6 +122,7 @@ neigh_chstate(struct ospf_neighbor *n, u8 state) { ifa->fadj++; schedule_rt_lsa(ifa->oa); + if (ifa->type == OSPF_IT_VLINK) schedule_rt_lsa(ifa->voa); schedule_net_lsa(ifa); } if (state == NEIGHBOR_EXSTART) @@ -422,12 +423,12 @@ bdr_election(struct ospf_iface *ifa) || ((ifa->bdrid != myid) && (nbdr == &me))) { if (ndr == NULL) - ifa->drip = me.dr = ipa_from_u32(0); + ifa->drip = me.dr = IPA_NONE; else ifa->drip = me.dr = ndr->ip; if (nbdr == NULL) - ifa->bdrip = me.bdr = ipa_from_u32(0); + ifa->bdrip = me.bdr = IPA_NONE; else ifa->bdrip = me.bdr = nbdr->ip; @@ -436,12 +437,12 @@ bdr_election(struct ospf_iface *ifa) } if (ndr == NULL) - ndrip = ipa_from_u32(0); + ndrip = IPA_NONE; else ndrip = ndr->ip; if (nbdr == NULL) - nbdrip = ipa_from_u32(0); + nbdrip = IPA_NONE; else nbdrip = nbdr->ip; @@ -453,7 +454,7 @@ bdr_election(struct ospf_iface *ifa) if (ndr == NULL) { ifa->drid = 0; - ifa->drip = ipa_from_u32(0); + ifa->drip = IPA_NONE; } else { @@ -464,7 +465,7 @@ bdr_election(struct ospf_iface *ifa) if (nbdr == NULL) { ifa->bdrid = 0; - ifa->bdrip = ipa_from_u32(0); + ifa->bdrip = IPA_NONE; } else { @@ -591,11 +592,12 @@ ospf_sh_neigh_info(struct ospf_neighbor *n) pos = "dr "; if (n->rid == ifa->bdrid) pos = "bdr "; - if (n->ifa->type == OSPF_IT_PTP) + if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_VLINK)) pos = "ptp "; cli_msg(-1013, "%-1I\t%3u\t%s/%s\t%-5s\t%-1I\t%-10s", n->rid, n->priority, - ospf_ns[n->state], pos, etime, n->ip, ifa->iface->name); + ospf_ns[n->state], pos, etime, n->ip, + (ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name)); } void diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index ccdc502..8f6b217 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -45,7 +45,7 @@ * Every area has its own area_disp() which is * responsible for late originating of router LSA, calculating * of the routing table and it also ages and flushes the LSAs. This - * function is called in regular intervals. + * function is called in regular intervals from ospf_disp() * To every &ospf_iface, we connect one or more * &ospf_neighbor's -- a structure containing many timers and queues * for building adjacency and for exchange of routing messages. @@ -72,7 +72,6 @@ static int ospf_rte_better(struct rte *new, struct rte *old); static int ospf_rte_same(struct rte *new, struct rte *old); -static void area_disp(timer *timer); static void ospf_disp(timer *timer); static void @@ -135,18 +134,11 @@ ospf_start(struct proto *p) add_tail(&po->area_list, NODE oa); po->areano++; oa->stub = ac->stub; - oa->tick = ac->tick; oa->areaid = ac->areaid; oa->gr = ospf_top_new(p->pool); s_init_list(&(oa->lsal)); oa->rt = NULL; oa->po = po; - oa->disp_timer = tm_new(p->pool); - oa->disp_timer->data = oa; - oa->disp_timer->randomize = 0; - oa->disp_timer->hook = area_disp; - oa->disp_timer->recurrent = oa->tick; - tm_start(oa->disp_timer, 2); add_area_nets(oa, ac); fib_init(&oa->rtr, p->pool, sizeof(ort), 16, ospf_rt_initort); if (oa->areaid == 0) po->backbone = oa; @@ -160,10 +152,8 @@ ospf_start(struct proto *p) struct ospf_iface_patt *ipatt; WALK_LIST(ac, c->area_list) { - WALK_LIST(ipatt, ac->patt_list) - { - if (ipatt->type == OSPF_IT_VLINK) ospf_iface_new(po, NULL, ac, ipatt); - } + WALK_LIST(ipatt, ac->vlink_list) + ospf_iface_new(po, NULL, ac, ipatt); } } return PS_UP; @@ -181,7 +171,7 @@ ospf_dump(struct proto *p) WALK_LIST(ifa, po->iface_list) { - OSPF_TRACE(D_EVENTS, "Interface: %s", ifa->iface->name); + OSPF_TRACE(D_EVENTS, "Interface: %s", (ifa->iface ? ifa->iface->name : "(null)")); OSPF_TRACE(D_EVENTS, "state: %u", ifa->state); OSPF_TRACE(D_EVENTS, "DR: %I", ifa->drid); OSPF_TRACE(D_EVENTS, "BDR: %I", ifa->bdrid); @@ -311,9 +301,8 @@ schedule_rtcalc(struct proto_ospf *po) * function for origination of router LSA and network LSAs. */ void -area_disp(timer * timer) +area_disp(struct ospf_area *oa) { - struct ospf_area *oa = timer->data; struct proto_ospf *po = oa->po; struct ospf_iface *ifa; @@ -324,7 +313,7 @@ area_disp(timer * timer) /* Now try to originate network LSA's */ WALK_LIST(ifa, po->iface_list) { - if (ifa->orignet && (ifa->an == oa->areaid)) + if (ifa->orignet && (ifa->oa == oa)) originate_net_lsa(ifa); } @@ -336,6 +325,10 @@ void ospf_disp(timer * timer) { struct proto_ospf *po = timer->data; + struct ospf_area *oa; + + WALK_LIST(oa, po->area_list) + area_disp(oa); /* Calculate routing table */ if (po->calcrt) @@ -555,6 +548,13 @@ ospf_reconfigure(struct proto *p, struct proto_config *c) struct area_net *anet, *antmp; int found; + /* FIXME Temporarily disabled */ + + return !memcmp(((byte *) old) + sizeof(struct proto_config), + ((byte *) new) + sizeof(struct proto_config), + sizeof(struct ospf_config) - sizeof(struct proto_config)); + + po->rfc1583 = new->rfc1583; schedule_rtcalc(po); @@ -576,19 +576,6 @@ ospf_reconfigure(struct proto *p, struct proto_config *c) if (!oa) return 0; - if (ac1->tick != ac2->tick) - { - if (oa->areaid == ac2->areaid) - { - oa->tick = ac2->tick; - tm_start(oa->disp_timer, oa->tick); - OSPF_TRACE(D_EVENTS, - "Changing tick interval on area %I from %d to %d", - oa->areaid, ac1->tick, ac2->tick); - break; - } - } - /* Change net_list */ fib_free(&oa->net_fib); add_area_nets(oa, ac2); @@ -840,6 +827,8 @@ ospf_sh(struct proto *p) } cli_msg(-1014, "%s:", p->name); + cli_msg(-1014, "RFC1583 compatibility: %s", (po->rfc1583 ? "enable" : "disabled")); + cli_msg(-1014, "RT scheduler tick: %d", po->tick); cli_msg(-1014, "Number of areas: %u", po->areano); WALK_LIST(oa, po->area_list) @@ -852,16 +841,18 @@ ospf_sh(struct proto *p) WALK_LIST(ifa, po->iface_list) { if (oa == ifa->oa) - ifano++; - WALK_LIST(n, ifa->neigh_list) { - nno++; - if (n->state == NEIGHBOR_FULL) - adjno++; + ifano++; + WALK_LIST(n, ifa->neigh_list) + { + nno++; + if (n->state == NEIGHBOR_FULL) + adjno++; + } } } cli_msg(-1014, "\t\tStub:\t%s", oa->stub ? "Yes" : "No"); - cli_msg(-1014, "\t\tRT scheduler tick:\t%u", oa->tick); + cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No"); cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano); cli_msg(-1014, "\t\tNumber of LSAs in DB:\t%u", oa->gr->hash_entries); cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno); diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 13a5f82..40452c2 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -52,8 +52,7 @@ #define LSINFINITY 0xffffff #define DEFAULT_OSPFTICK 1 -#define DEFAULT_AREATICK 1 -#define DEFAULT_RFC1583 1 /* compatibility with rfc1583 */ +#define DEFAULT_RFC1583 0 /* compatibility with rfc1583 */ struct ospf_config @@ -90,8 +89,8 @@ struct ospf_area_config node n; u32 areaid; int stub; - unsigned tick; list patt_list; + list vlink_list; list net_list; }; @@ -130,7 +129,6 @@ struct ospf_iface struct iface *iface; /* Nest's iface */ struct ospf_area *oa; struct object_lock *lock; - u32 an; /* Area number */ sock *hello_sk; /* Hello socket */ sock *dr_sk; /* For states DR or BACKUP */ sock *ip_sk; /* IP socket (for DD ...) */ @@ -519,7 +517,6 @@ struct ospf_area int stub; int trcap; /* Transit capability? */ struct proto_ospf *po; - unsigned tick; struct fib rtr; /* Routing tables for routers */ union options opt; /* RFC2328 - A.2 */ }; diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index 488a3a2..92e0522 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -25,7 +25,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type) pkt->type = h_type; pkt->routerid = htonl(p->cf->global->router_id); - pkt->areaid = htonl(ifa->an); + pkt->areaid = htonl(ifa->oa->areaid); pkt->autype = htons(ifa->autype); pkt->checksum = 0; } @@ -219,17 +219,32 @@ ospf_rx_hook(sock * sk, int size) { struct ospf_packet *ps; struct ospf_iface *ifa = (struct ospf_iface *) (sk->data); + struct proto_ospf *po = ifa->proto; struct proto *p = (struct proto *) (ifa->proto); struct ospf_neighbor *n; int osize; char *mesg = "Bad OSPF packet from "; + struct ospf_iface *iff; if (ifa->stub) return (1); + ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size); + + if ((ifa->oa->areaid != 0) && (ntohl(ps->areaid) == 0)) + { + WALK_LIST(iff, po->iface_list) + { + if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface) && + (iff->voa = ifa->oa) && ipa_equal(sk->faddr, iff->vip)) + { + return 1; /* Packet is for VLINK */ + } + } + } + DBG("%s: RX_Hook called on interface %s.\n", p->name, sk->iface->name); - ps = (struct ospf_packet *) ipv4_skip_header(sk->rbuf, &size); osize = ntohs(ps->length); if (ps == NULL) { @@ -263,7 +278,7 @@ ospf_rx_hook(sock * sk, int size) return 1; } - if (ntohl(ps->areaid) != ifa->an) + if (ntohl(ps->areaid) != ifa->oa->areaid) { log(L_ERR "%s%I - other area %ld", mesg, sk->faddr, ps->areaid); return 1; @@ -374,9 +389,9 @@ ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state) void ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa) { - if (ipa_compare(ifa->drip, ipa_from_u32(0)) != 0) + if (!ipa_equal(ifa->drip, IPA_NONE)) ospf_send_to(sk, ifa->drip, ifa); - if (ipa_compare(ifa->bdrip, ipa_from_u32(0)) != 0) + if (!ipa_equal(ifa->bdrip, IPA_NONE)) ospf_send_to(sk, ifa->bdrip, ifa); } diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 3d2ee51..ef3d44d 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -9,7 +9,7 @@ #include "ospf.h" static void add_cand(list * l, struct top_hash_entry *en, - struct top_hash_entry *par, u16 dist, struct ospf_area *oa); + struct top_hash_entry *par, u16 dist, struct ospf_area *oa, int vlink); static void calc_next_hop(struct top_hash_entry *en, struct top_hash_entry *par, struct ospf_area *oa); @@ -24,7 +24,7 @@ fill_ri(orta * orta) orta->oa = NULL; orta->metric1 = LSINFINITY; orta->metric2 = LSINFINITY; - orta->nh = ipa_from_u32(0); + orta->nh = IPA_NONE; orta->ifa = NULL; orta->ar = NULL; orta->tag = 0; @@ -63,8 +63,7 @@ ri_better(struct proto_ospf *po, orta * new, ort *nefn, orta * old, ort *oefn, i { if(new->oa->areaid == 0) newtype = RTS_OSPF_IA; if(old->oa->areaid == 0) oldtype = RTS_OSPF_IA; - -} + } if (new->type < old->type) return 1; @@ -146,6 +145,7 @@ ospf_rt_spfa(struct ospf_area *oa) struct ospf_iface *iface; struct top_hash_entry *act, *tmp; node *n; + int vlink; if (oa->rt == NULL) @@ -155,7 +155,7 @@ ospf_rt_spfa(struct ospf_area *oa) oa->areaid); if (oa->rt->dist != LSINFINITY) - ospf_age(oa); + bug("Aging was not processed."); init_list(&oa->cand); /* Empty list of candidates */ oa->trcap = 0; @@ -202,6 +202,7 @@ ospf_rt_spfa(struct ospf_area *oa) DBG(" Number of links: %u\n", rt->links); for (i = 0; i < rt->links; i++) { + vlink = 0; tmp = NULL; rtl = (rr + i); DBG(" Working on link: %I (type: %u) ", rtl->id, rtl->type); @@ -238,6 +239,7 @@ ospf_rt_spfa(struct ospf_area *oa) break; case LSART_VLNK: + vlink = 1; case LSART_PTP: tmp = ospf_hash_find(oa->gr, rtl->id, rtl->id, LSA_T_RT); DBG("PTP found.\n"); @@ -249,7 +251,7 @@ ospf_rt_spfa(struct ospf_area *oa) if (tmp) DBG("Going to add cand, Mydist: %u, Req: %u\n", tmp->dist, act->dist + rtl->metric); - add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa); + add_cand(&oa->cand, tmp, act, act->dist + rtl->metric, oa, vlink); } break; case LSA_T_NET: @@ -275,7 +277,7 @@ ospf_rt_spfa(struct ospf_area *oa) DBG("Found :-)\n"); else DBG("Not found!\n"); - add_cand(&oa->cand, tmp, act, act->dist, oa); + add_cand(&oa->cand, tmp, act, act->dist, oa, 0); } break; } @@ -287,15 +289,24 @@ ospf_rt_spfa(struct ospf_area *oa) if ((iface->type == OSPF_IT_VLINK) && (iface->voa == oa)) { if ((tmp = ospf_hash_find(oa->gr, iface->vid, iface->vid, LSA_T_RT)) && - ipa_equal(tmp->lb, IPA_NONE)) + (!ipa_equal(tmp->lb, IPA_NONE))) { - DBG("Vlink peer found\n"); - ospf_iface_sm(iface, ISM_UP); /* FIXME: Add slave iface! */ + if ((iface->state != OSPF_IS_PTP) || (iface->iface != tmp->nhi) || (!ipa_equal(iface->vip, tmp->lb))) + { + OSPF_TRACE(D_EVENTS, "Vlink peer %I found", tmp->lsa.id); + ospf_iface_sm(iface, ISM_DOWN); + iface->iface = tmp->nhi; + iface->vip = tmp->lb; + ospf_iface_sm(iface, ISM_UP); + } } else { - DBG("Vlink peer not found\n"); - ospf_iface_sm(iface, ISM_DOWN); + if (iface->state > OSPF_IS_DOWN) + { + OSPF_TRACE(D_EVENTS, "Vlink peer %I lost", iface->vid); + ospf_iface_sm(iface, ISM_DOWN); + } } } } @@ -367,7 +378,7 @@ ospf_rt_sum_tr(struct ospf_area *oa) { struct proto *p = &oa->po->proto; struct proto_ospf *po = oa->po; - struct ospf_area *bb, *atmp; + struct ospf_area *bb = po->backbone; ip_addr *mask, ip, abrip; struct top_hash_entry *en; int mlen = -1, type = -1; @@ -375,17 +386,6 @@ ospf_rt_sum_tr(struct ospf_area *oa) ort *re = NULL, *abr; orta nf; - bb = NULL; - - WALK_LIST(atmp, po->area_list) - { - if(atmp->areaid == 0) - { - bb = atmp; - break; - } - } - if(!bb) return; WALK_SLIST(en, oa->lsal) @@ -672,7 +672,7 @@ ospf_ext_spfa(struct ospf_area *oa) if (!(nf1->n.capa & ORTA_ASBR)) continue; /* It is not ASBR */ - if (ipa_compare(lt->fwaddr, ipa_from_u32(0)) == 0) + if (ipa_equal(lt->fwaddr, IPA_NONE)) { if (lt->etm.etos.ebit) { /* FW address == 0 */ @@ -742,7 +742,7 @@ ospf_ext_spfa(struct ospf_area *oa) /* Add LSA into list of candidates in Dijkstra's algorithm */ static void add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, - u16 dist, struct ospf_area *oa) + u16 dist, struct ospf_area *oa, int vlink) { node *prev, *n; int added = 0; @@ -773,6 +773,7 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, en->nh = IPA_NONE; calc_next_hop(en, par, oa); + //if (vlink) en->nh = IPA_NONE; if (!en->nhi) return; /* We cannot find next hop, ignore it */ @@ -901,8 +902,9 @@ rt_sync(struct proto_ospf *po) struct fib_iterator fit; struct fib *fib = &po->rtf; ort *nf; - struct ospf_area *oa; + struct ospf_area *oa, *oaa; struct area_net *anet; + int flush; OSPF_TRACE(D_EVENTS, "Starting routing table synchronisation"); @@ -929,6 +931,27 @@ again1: a0.aflags = 0; a0.iface = nf->n.ifa; a0.gw = nf->n.nh; + if(!neigh_find(p, &nf->n.nh, 0)) + { + int found = 0; + struct ospf_iface *ifa; + struct top_hash_entry *en; + DBG("Trying to find correct next hop"); + WALK_LIST(ifa, po->iface_list) + { + if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh)) + { + if ((en = ospf_hash_find(ifa->voa->gr, ifa->vid, ifa->vid, LSA_T_RT)) && + (!ipa_equal(en->nh, IPA_NONE))) + { + a0.gw = en->nh; + found = 1; + } + break; + } + } + if (!found) nf->n.metric1 = LSINFINITY; /* Delete it */ + } ne = net_get(p->table, nf->fn.prefix, nf->fn.pxlen); check_sum_lsa(po, nf, ORT_NET); if (nf->n.metric1 < LSINFINITY) @@ -978,10 +1001,17 @@ again2: /* Check condensed summary LSAs */ FIB_WALK(&oa->net_fib, nftmp) { + flush = 1; anet = (struct area_net *) nftmp; if((!anet->hidden) && anet->active && (!oa->trcap)) - originate_sum_lsa(oa, &anet->fn, ORT_NET, 1); - else flush_sum_lsa(oa, &anet->fn, ORT_NET); + flush = 0; + + WALK_LIST(oaa, po->area_list) + { + if (oaa == oa) continue; + if(flush) flush_sum_lsa(oaa, &anet->fn, ORT_NET); + else originate_sum_lsa(oaa, &anet->fn, ORT_NET, 1); + } } FIB_WALK_END; } diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 562ddb5..4854721 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -36,7 +36,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length) WALK_LIST(ifa, po->iface_list) { - if ((ifa->an == oa->areaid) && (ifa->state != OSPF_IS_DOWN)) + if ((ifa->oa == oa) && (ifa->state != OSPF_IS_DOWN)) { i++; } @@ -51,7 +51,10 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length) WALK_LIST(ifa, po->iface_list) { - if ((ifa->an != oa->areaid) || (ifa->state == OSPF_IS_DOWN)) + if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (ifa->state > OSPF_IS_DOWN)) + rt->veb.bit.v = 1; + + if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN)) continue; if (ifa->state == OSPF_IS_LOOP) @@ -146,7 +149,6 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length) ln->id = neigh->rid; ln->metric = ifa->cost; ln->notos = 0; - rt->veb.bit.v = 1; } else { @@ -351,14 +353,14 @@ originate_ext_lsa_body(net * n, rte * e, struct proto_ospf *po, et->etm.etos.ebit = 1; } et->tag = tag; - if (ipa_compare(e->attrs->gw, ipa_from_u32(0)) != 0) + if (!ipa_equal(e->attrs->gw, IPA_NONE)) { if (ospf_iface_find((struct proto_ospf *) p, e->attrs->iface) != NULL) inas = 1; } if (!inas) - et->fwaddr = ipa_from_u32(0); + et->fwaddr = IPA_NONE; else et->fwaddr = e->attrs->gw; return ext; @@ -416,7 +418,8 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type) { en->lsa.age = LSA_MAXAGE; en->lsa.sn = LSA_MAXSEQNO; - OSPF_TRACE(D_EVENTS, "Flushing summary lsa."); + lsasum_calculate(&en->lsa, sum); + OSPF_TRACE(D_EVENTS, "Flushing summary lsa. (id=%I, type=%d)", en->lsa.id, en->lsa.type); ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); if (can_flush_lsa(oa)) flush_lsa(en, oa); break; @@ -425,9 +428,6 @@ flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type) } } - - - void originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metric) { @@ -436,8 +436,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri struct top_hash_entry *en; u32 rtid = po->proto.cf->global->router_id; struct ospf_lsa_header lsa; - void *body = NULL; - int i, max, mlen = fn->pxlen, found = 0, free = -1; + int i, max, mlen = fn->pxlen, free = 0; struct ospf_lsa_sum *sum = NULL; union ospf_lsa_sum_tm *tm; lsa.type = LSA_T_SUM_NET; @@ -461,7 +460,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri lsa.id = ipa_to_u32(fn->prefix) + i; if ((en = ospf_hash_find_header(oa->gr, &lsa)) == NULL) { - if (free < 0) free = i; + if (!free) free = lsa.id; } else { @@ -477,7 +476,7 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri } } - if(free < 0) + if(!free) { log("%s: got more routes for one /%d network then %d, ignoring", p->name, fn->pxlen, max); @@ -485,9 +484,6 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri } lsa.id = free; - sum = en->lsa_body; - tm = (union ospf_lsa_sum_tm *) (sum + 1); - OSPF_TRACE(D_EVENTS, "Originating summary (type %d) lsa for %I/%d.", lsa.type, fn->prefix, fn->pxlen); @@ -497,8 +493,8 @@ originate_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type, int metri tm->metric = metric; tm->tos.tos = 0; - lsasum_calculate(&lsa, body); - en = lsa_install_new(&lsa, body, oa); + lsasum_calculate(&lsa, sum); + en = lsa_install_new(&lsa, sum, oa); ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); } @@ -515,6 +511,12 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest) if ((nf->n.type > RTS_OSPF_IA) && (nf->o.type > RTS_OSPF_IA)) return; +#ifdef LOCAL_DEBUG + DBG("Checking...dest = %d, %I/%d", dest, nf->fn.prefix, nf->fn.pxlen); + if (nf->n.oa) DBG("New: met=%d, oa=%d", nf->n.metric1, nf->n.oa->areaid); + if (nf->o.oa) DBG("Old: met=%d, oa=%d", nf->o.metric1, nf->o.oa->areaid); +#endif + WALK_LIST(oa, po->area_list) { flush = 0; @@ -522,7 +524,7 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest) flush = 1; if ((dest == ORT_ROUTER) && (!(nf->n.capa & ORTA_ABR))) flush = 1; - if (nf->n.oa->areaid == oa->areaid) + if ((!nf->n.oa) || (nf->n.oa->areaid == oa->areaid)) flush = 1; /* FIXME: Test next hop - is it in actual area? */ if ((dest == ORT_ROUTER) && oa->stub) @@ -531,7 +533,8 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest) mlen = nf->fn.pxlen; ip = ipa_and(nf->fn.prefix, ipa_mkmask(mlen)); - if((!oa->trcap) && fib_route(&oa->net_fib, ip, mlen)) /* The route fits into some area */ + if ((!flush) && (!nf->n.oa->trcap) && + fib_route(&nf->n.oa->net_fib, ip, mlen)) /* The route fits into area networks */ flush = 1; if(flush) /* FIXME Go on... */ @@ -543,20 +546,6 @@ check_sum_lsa(struct proto_ospf *po, ort *nf, int dest) } } -void -check_sum_areas(struct proto_ospf *po) -{ - struct proto *p = &po->proto; - struct ospf_area *oa; - struct area_net *anet; - - WALK_LIST(oa, po->area_list) - { - ; /* FIXME */ - } -} - - /** * originate_ext_lsa - new route received from nest and filters * @n: network prefix and mask @@ -806,8 +795,8 @@ ospf_hash_get(struct top_graph *f, u32 lsa, u32 rtr, u32 type) e->color = OUTSPF; e->dist = LSINFINITY; e->nhi = NULL; - e->nh = ipa_from_u32(0); - e->lb = ipa_from_u32(0); + e->nh = IPA_NONE; + e->lb = IPA_NONE; e->lsa.id = lsa; e->lsa.rt = rtr; e->lsa.type = type; @@ -852,8 +841,8 @@ ospf_top_dump(struct top_graph *f, struct proto *p) struct top_hash_entry *e = f->hash_table[i]; while (e) { - OSPF_TRACE(D_EVENTS, "\t%1x %-1I %-1I %4u 0x%08x", - e->lsa.type, e->lsa.id, e->lsa.rt, e->lsa.age, e->lsa.sn); + OSPF_TRACE(D_EVENTS, "\t%1x %-1I %-1I %4u 0x%08x 0x%04x", + e->lsa.type, e->lsa.id, e->lsa.rt, e->lsa.age, e->lsa.sn, e->lsa.checksum); e = e->next; } } |