diff options
-rw-r--r-- | usr.sbin/ospfd/interface.c | 14 | ||||
-rw-r--r-- | usr.sbin/ospfd/neighbor.c | 17 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfe.c | 311 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfe.h | 4 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde.c | 7 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde.h | 5 | ||||
-rw-r--r-- | usr.sbin/ospfd/rde_lsdb.c | 39 |
7 files changed, 272 insertions, 125 deletions
diff --git a/usr.sbin/ospfd/interface.c b/usr.sbin/ospfd/interface.c index 04489dabe2d..b57d6bf49f9 100644 --- a/usr.sbin/ospfd/interface.c +++ b/usr.sbin/ospfd/interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.c,v 1.7 2005/02/09 17:41:16 claudio Exp $ */ +/* $OpenBSD: interface.c,v 1.8 2005/02/09 20:40:23 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -138,6 +138,9 @@ if_fsm(struct iface *iface, enum iface_event event) if (new_state != 0) iface->state = new_state; + if (iface->state != old_state) + orig_rtr_lsa(iface->area); + log_debug("fsm_if: event %s resulted in action %s and changing " "state for interface %s from %s to %s", if_event_name(event), if_action_name(iface_fsm[i].action), @@ -241,6 +244,7 @@ if_init(struct ospfd_conf *xconf) struct area *area = NULL; struct iface *iface = NULL; + /* XXX wrong as hell */ if ((xconf->ospf_socket = socket(AF_INET, SOCK_RAW, IPPROTO_OSPF)) == -1) { log_warn("if_init: error creating socket"); @@ -419,6 +423,7 @@ if_act_elect(struct iface *iface) struct nbr *nbr, *bdr = NULL, *dr = NULL; int round = 0; int changed = 0; + int old_state; char b1[16], b2[16], b3[16], b4[16]; log_debug("if_act_elect: interface %s", iface->name); @@ -488,6 +493,7 @@ start: * After the second round still DR or BDR change state to DR or BDR, * etc. */ + old_state = iface->state; if (dr == iface->self) iface->state = IF_STA_DR; else if (bdr == iface->self) @@ -506,11 +512,15 @@ start: iface->dr = dr; iface->bdr = bdr; - if (changed) + if (changed) { LIST_FOREACH(nbr, &iface->nbr_list, entry) { if (nbr->state & NBR_STA_BIDIR) nbr_fsm(nbr, NBR_EVT_ADJ_OK); } + orig_rtr_lsa(iface->area); + if (iface->state & IF_STA_DR || old_state & IF_STA_DR) + orig_net_lsa(iface); + } if (if_start_hello_timer(iface)) { log_warnx("if_act_elect: cannot schedule hello_timer"); diff --git a/usr.sbin/ospfd/neighbor.c b/usr.sbin/ospfd/neighbor.c index 68872cd5142..e4db3637911 100644 --- a/usr.sbin/ospfd/neighbor.c +++ b/usr.sbin/ospfd/neighbor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: neighbor.c,v 1.8 2005/02/09 16:14:23 claudio Exp $ */ +/* $OpenBSD: neighbor.c,v 1.9 2005/02/09 20:40:23 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -197,14 +197,23 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event) if (new_state != 0) nbr->state = new_state; - if (nbr->state != old_state) + /* state change inform RDE */ + if (old_state != nbr->state) ospfe_imsg_compose_rde(IMSG_NEIGHBOR_CHANGE, nbr->peerid, 0, &new_state, sizeof(new_state)); - if (old_state & ~NBR_STA_PRELIM && new_state & NBR_STA_PRELIM) - /* bidirectional communication lost */ + /* bidirectional communication lost */ + if (old_state & ~NBR_STA_PRELIM && nbr->state & NBR_STA_PRELIM) if_fsm(nbr->iface, IF_EVT_NBR_CHNG); + /* neighbor changed from/to FULL originate new rtr and net LSA */ + if (old_state != nbr->state && (old_state & NBR_STA_FULL || + nbr->state & NBR_STA_FULL)) { + orig_rtr_lsa(nbr->iface->area); + if (nbr->iface->state & IF_STA_DR) + orig_net_lsa(nbr->iface); + } + if (old_state != nbr->state) { nbr->stats.sta_chng++; log_debug("nbr_fsm: event %s resulted in action %s and " diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c index 4a98af08bc7..b6aae0bf494 100644 --- a/usr.sbin/ospfd/ospfe.c +++ b/usr.sbin/ospfd/ospfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.c,v 1.4 2005/02/07 05:51:00 david Exp $ */ +/* $OpenBSD: ospfe.c,v 1.5 2005/02/09 20:40:23 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -43,9 +43,6 @@ void ospfe_sig_handler(int, short, void *); void ospfe_shutdown(void); -void orig_lsa(void); -void orig_rtr_lsa(struct area *); -void orig_net_lsa(struct iface *); volatile sig_atomic_t ospfe_quit = 0; struct ospfd_conf *oeconf = NULL; @@ -164,8 +161,6 @@ ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2], } } - orig_lsa(); - event_dispatch(); ospfe_shutdown(); @@ -528,155 +523,251 @@ ospfe_dispatch_rde(int fd, short event, void *bula) } void -orig_lsa(void) -{ - struct area *area; - struct iface *iface; - - LIST_FOREACH(area, &oeconf->area_list, entry) { - orig_rtr_lsa(area); - LIST_FOREACH(iface, &area->iface_list, entry) - orig_net_lsa(iface); - } -} - -void orig_rtr_lsa(struct area *area) { - struct lsa *lsa; + struct lsa_hdr lsa_hdr; + struct lsa_rtr lsa_rtr; + struct lsa_rtr_link rtr_link; struct iface *iface; - char *buf; - struct lsa_rtr_link *rtr_link; - int num_links = 0; - u_int16_t len; + struct buf *buf; + struct nbr *nbr, *self = NULL; + u_int16_t num_links = 0; + u_int16_t chksum; log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id)); - if ((buf = calloc(1, READ_BUF_SIZE)) == NULL) + if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE /* XXX */)) == NULL) fatal("orig_rtr_lsa"); - /* LSA header */ - lsa = (struct lsa *)buf; - lsa->hdr.age = htons(DEFAULT_AGE); /* XXX */ - lsa->hdr.opts = oeconf->options; /* XXX */ - lsa->hdr.type = LSA_TYPE_ROUTER; - lsa->hdr.ls_id = oeconf->rtr_id.s_addr; - lsa->hdr.adv_rtr = oeconf->rtr_id.s_addr; - lsa->hdr.seq_num = htonl(INIT_SEQ_NUM); - lsa->hdr.ls_chksum = 0; /* updated later */ - lsa->hdr.len = 0; /* updated later */ - len = sizeof(struct lsa_hdr) + sizeof(struct lsa_rtr); + /* reserve space for LSA header and LSA Router header */ + if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL) + fatal("orig_rtr_lsa: buf_reserve failed"); + + if (buf_reserve(buf, sizeof(lsa_rtr)) == NULL) + fatal("orig_rtr_lsa: buf_reserve failed"); /* links */ LIST_FOREACH(iface, &area->iface_list, entry) { log_debug("orig_rtr_lsa: interface %s", iface->name); - rtr_link = (struct lsa_rtr_link *)(buf + len); + if (self == NULL && iface->self != NULL) + self = iface->self; + + if (iface->state & IF_STA_DOWN) + continue; + + bzero(&rtr_link, sizeof(rtr_link)); + + if (iface->state & IF_STA_LOOPBACK) { + rtr_link.id = iface->addr.s_addr; + rtr_link.data = 0xffffffff; + rtr_link.type = LINK_TYPE_STUB_NET; + num_links++; + if (buf_add(buf, &rtr_link, sizeof(rtr_link))) + fatalx("orig_rtr_lsa: buf_add failed"); + continue; + } + switch (iface->type) { case IF_TYPE_POINTOPOINT: - case IF_TYPE_VIRTUALLINK: - log_debug("orig_rtr_lsa: not supported, interface %s", - iface->name); - break; - case IF_TYPE_BROADCAST: - if (iface->state == IF_STA_DOWN) - break; - - if ((iface->state == IF_STA_WAITING) || - iface->dr == NULL) { /* XXX */ - log_debug("orig_rtr_lsa: stub net, " + LIST_FOREACH(nbr, &iface->nbr_list, entry) + if (nbr != iface->self && + nbr->state & NBR_STA_FULL) + break; + if (nbr) { + log_debug("orig_rtr_lsa: point-to-point, " "interface %s", iface->name); - - rtr_link->id = - iface->addr.s_addr & iface->mask.s_addr; - rtr_link->data = iface->mask.s_addr; - rtr_link->type = LINK_TYPE_STUB_NET; - } else { - log_debug("orig_rtr_lsa: transit net, " + rtr_link.id = nbr->addr.s_addr; + rtr_link.data = iface->addr.s_addr; + rtr_link.type = LINK_TYPE_POINTTOPOINT; + rtr_link.metric = htons(iface->metric); + num_links++; + if (buf_add(buf, &rtr_link, sizeof(rtr_link))) + fatalx("orig_rtr_lsa: buf_add failed"); + } + if (iface->state & IF_STA_POINTTOPOINT) { + log_debug("orig_rtr_lsa: stub net, " "interface %s", iface->name); - - rtr_link->id = iface->dr->addr.s_addr; - rtr_link->data = iface->addr.s_addr; - rtr_link->type = LINK_TYPE_TRANSIT_NET; + bzero(&rtr_link, sizeof(rtr_link)); + if (nbr) { + rtr_link.id = nbr->addr.s_addr; + rtr_link.data = 0xffffffff; + } else { + rtr_link.id = iface->addr.s_addr; + rtr_link.data = iface->mask.s_addr; + } + rtr_link.metric = htons(iface->metric); + rtr_link.type = LINK_TYPE_STUB_NET; + num_links++; + if (buf_add(buf, &rtr_link, sizeof(rtr_link))) + fatalx("orig_rtr_lsa: buf_add failed"); + } + continue; + case IF_TYPE_BROADCAST: + case IF_TYPE_NBMA: + if ((iface->state & IF_STA_MULTI)) { + if (iface->dr == iface->self) { + LIST_FOREACH(nbr, &iface->nbr_list, + entry) + if (nbr != iface->self && + nbr->state & NBR_STA_FULL) + break; + } else + nbr = iface->dr; + + if (nbr && nbr->state & NBR_STA_FULL) { + log_debug("orig_rtr_lsa: transit net, " + "interface %s", iface->name); + + rtr_link.id = iface->dr->addr.s_addr; + rtr_link.data = iface->addr.s_addr; + rtr_link.type = LINK_TYPE_TRANSIT_NET; + break; + } } + log_debug("orig_rtr_lsa: stub net, " + "interface %s", iface->name); - rtr_link->num_tos = 0; - rtr_link->metric = htons(iface->metric); - num_links++; - len += sizeof(struct lsa_rtr_link); + rtr_link.id = + iface->addr.s_addr & iface->mask.s_addr; + rtr_link.data = iface->mask.s_addr; + rtr_link.type = LINK_TYPE_STUB_NET; break; - case IF_TYPE_NBMA: - case IF_TYPE_POINTOMULTIPOINT: + case IF_TYPE_VIRTUALLINK: log_debug("orig_rtr_lsa: not supported, interface %s", iface->name); - break; + continue; + case IF_TYPE_POINTOMULTIPOINT: + log_debug("orig_rtr_lsa: stub net, " + "interface %s", iface->name); + rtr_link.id = iface->addr.s_addr; + rtr_link.data = 0xffffffff; + rtr_link.type = LINK_TYPE_STUB_NET; + num_links++; + if (buf_add(buf, &rtr_link, sizeof(rtr_link))) + fatalx("orig_rtr_lsa: buf_add failed"); + + LIST_FOREACH(nbr, &iface->nbr_list, entry) { + if (nbr != iface->self && + nbr->state & NBR_STA_FULL) { + bzero(&rtr_link, sizeof(rtr_link)); + log_debug("orig_rtr_lsa: " + "point-to-point, interface %s", + iface->name); + rtr_link.id = nbr->addr.s_addr; + rtr_link.data = iface->addr.s_addr; + rtr_link.type = LINK_TYPE_POINTTOPOINT; + rtr_link.metric = htons(iface->metric); + num_links++; + if (buf_add(buf, &rtr_link, + sizeof(rtr_link))) + fatalx("orig_rtr_lsa: " + "buf_add failed"); + } + } + continue; default: fatalx("orig_rtr_lsa: unknown interface type"); } - } - lsa->data.rtr.flags = 0; /* XXX */ - lsa->data.rtr.dummy = 0; - lsa->data.rtr.nlinks = htons(num_links); - - lsa->hdr.len = htons(len); + rtr_link.num_tos = 0; + rtr_link.metric = htons(iface->metric); + num_links++; + if (buf_add(buf, &rtr_link, sizeof(rtr_link))) + fatalx("orig_rtr_lsa: buf_add failed"); + } - lsa->hdr.ls_chksum = htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET)); + /* LSA router header */ + lsa_rtr.flags = 0; /* XXX */ + lsa_rtr.dummy = 0; + lsa_rtr.nlinks = htons(num_links); + memcpy(buf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_rtr)), + &lsa_rtr, sizeof(lsa_rtr)); - imsg_compose(ibuf_rde, IMSG_LS_UPD, - LIST_FIRST(&area->iface_list)->self->peerid, 0, -1, buf, - ntohs(lsa->hdr.len)); + /* LSA header */ + lsa_hdr.age = htons(DEFAULT_AGE); + lsa_hdr.opts = oeconf->options; /* XXX */ + lsa_hdr.type = LSA_TYPE_ROUTER; + lsa_hdr.ls_id = oeconf->rtr_id.s_addr; + lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; + lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); + lsa_hdr.len = htons(buf->wpos); + lsa_hdr.ls_chksum = 0; /* updated later */ + memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr)); + + chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET)); + memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)), + &chksum, sizeof(chksum)); + + if (self) + imsg_compose(ibuf_rde, IMSG_LS_UPD, + self->peerid, 0, -1, buf->buf, buf->wpos); + else + log_warnx("orig_rtr_lsa: empty area %s", + inet_ntoa(area->id)); + + buf_free(buf); } void orig_net_lsa(struct iface *iface) { - struct lsa *lsa; + struct lsa_hdr lsa_hdr; struct nbr *nbr; - char *buf; + struct buf *buf; int num_rtr = 0; - u_int16_t len; + u_int16_t chksum; log_debug("orig_net_lsa: iface %s", iface->name); - /* XXX if not dr quit */ - /* ... */ - - if ((buf = calloc(1, READ_BUF_SIZE)) == NULL) + if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE /* XXX */)) == NULL) fatal("orig_net_lsa"); - /* LSA header */ - lsa = (struct lsa *)buf; - lsa->hdr.age = htons(DEFAULT_AGE); /* XXX */ - lsa->hdr.opts = oeconf->options; /* XXX */ - lsa->hdr.type = LSA_TYPE_NETWORK; - lsa->hdr.ls_id = oeconf->rtr_id.s_addr; - lsa->hdr.adv_rtr = oeconf->rtr_id.s_addr; - lsa->hdr.seq_num = htonl(INIT_SEQ_NUM); - lsa->hdr.ls_chksum = 0; /* updated later */ - lsa->hdr.len = 0; /* updated later */ - len = sizeof(lsa->hdr); - - lsa->data.net.mask = iface->mask.s_addr; - len += sizeof(lsa->data.net.mask); - - /* attached routers */ + /* reserve space for LSA header and LSA Router header */ + if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL) + fatal("orig_net_lsa: buf_reserve failed"); + + /* LSA net mask and then all fully adjacent routers */ + if (buf_add(buf, &iface->mask, sizeof(iface->mask))) + fatal("orig_net_lsa: buf_add failed"); + /* fully adjacent neighbors + self */ - LIST_FOREACH(nbr, &iface->nbr_list, entry) { - if (nbr->state != NBR_STA_FULL) { /* XXX */ - lsa->data.net.att_rtr[num_rtr] = nbr->id.s_addr; + LIST_FOREACH(nbr, &iface->nbr_list, entry) + if (nbr->state & NBR_STA_FULL) { + if (buf_add(buf, &nbr->id, sizeof(nbr->id))) + fatal("orig_net_lsa: buf_add failed"); num_rtr++; - len += sizeof(nbr->id); } - } - lsa->hdr.len = htons(len); + if (num_rtr == 1) { + /* non transit net therefor no need to generate a net lsa */ + buf_free(buf); + return; + } - lsa->hdr.ls_chksum = htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET)); -/* - imsg_compose(ibuf_rde, IMSG_LS_UPD, iface->self->peerid, 0, -1, buf, - ntohs(lsa->hdr.len)); -*/ + /* LSA header */ + if (iface->state & IF_STA_DR) + lsa_hdr.age = htons(DEFAULT_AGE); + else + lsa_hdr.age = htons(MAX_AGE); + + lsa_hdr.opts = oeconf->options; /* XXX */ + lsa_hdr.type = LSA_TYPE_NETWORK; + lsa_hdr.ls_id = iface->addr.s_addr; + lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr; + lsa_hdr.seq_num = htonl(INIT_SEQ_NUM); + lsa_hdr.len = htons(buf->wpos); + lsa_hdr.ls_chksum = 0; /* updated later */ + memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr)); + + chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET)); + memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)), + &chksum, sizeof(chksum)); + + imsg_compose(ibuf_rde, IMSG_LS_UPD, iface->self->peerid, 0, -1, + buf->buf, buf->wpos); + + buf_free(buf); } u_int32_t diff --git a/usr.sbin/ospfd/ospfe.h b/usr.sbin/ospfd/ospfe.h index b4ac850093d..3a5a488a179 100644 --- a/usr.sbin/ospfd/ospfe.h +++ b/usr.sbin/ospfd/ospfe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.h,v 1.3 2005/02/02 19:15:07 henning Exp $ */ +/* $OpenBSD: ospfe.h,v 1.4 2005/02/09 20:40:23 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -171,6 +171,8 @@ int ospfe_imsg_compose_rde(int, u_int32_t, pid_t, void *, u_int32_t ospfe_router_id(void); void ospfe_iface_ctl(struct ctl_conn *, unsigned int); void ospfe_nbr_ctl(struct ctl_conn *); +void orig_rtr_lsa(struct area *); +void orig_net_lsa(struct iface *); /* interface.c */ int if_fsm(struct iface *, enum iface_event); diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c index 2d48a1e4b2a..b835a90515c 100644 --- a/usr.sbin/ospfd/rde.c +++ b/usr.sbin/ospfd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.3 2005/02/02 19:15:07 henning Exp $ */ +/* $OpenBSD: rde.c,v 1.4 2005/02/09 20:40:23 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -351,6 +351,11 @@ rde_dispatch_imsg(int fd, short event, void *bula) else db_hdr = &v->lsa->hdr; + if (nbr->self) { + lsa_merge(nbr, lsa, v); + break; + } + r = lsa_newer(&lsa->hdr, db_hdr); if (r > 0) { /* new LSA newer than DB */ diff --git a/usr.sbin/ospfd/rde.h b/usr.sbin/ospfd/rde.h index 232ea6dc24d..404c036c70a 100644 --- a/usr.sbin/ospfd/rde.h +++ b/usr.sbin/ospfd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.2 2005/01/28 17:53:33 norby Exp $ */ +/* $OpenBSD: rde.h,v 1.3 2005/02/09 20:40:23 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -63,7 +63,7 @@ u_int32_t rde_router_id(void); void rde_nbr_del(struct rde_nbr *); int rde_nbr_loading(struct area *); -/* rde_spf.c */ +/* rde_lsdb.c */ void lsa_init(struct lsa_tree *); int lsa_compare(struct vertex *, struct vertex *); void vertex_free(struct vertex *); @@ -75,6 +75,7 @@ void lsa_del(struct rde_nbr *, struct lsa_hdr *); struct vertex *lsa_find(struct area *, u_int8_t, u_int32_t, u_int32_t); void lsa_snap(struct area *, u_int32_t); void lsa_dump(struct lsa_tree *, pid_t); +void lsa_merge(struct rde_nbr *, struct lsa *, struct vertex *); RB_PROTOTYPE(lsa_tree, vertex, entry, lsa_compare) diff --git a/usr.sbin/ospfd/rde_lsdb.c b/usr.sbin/ospfd/rde_lsdb.c index eafb5ed0502..2b5fef75c6a 100644 --- a/usr.sbin/ospfd/rde_lsdb.c +++ b/usr.sbin/ospfd/rde_lsdb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_lsdb.c,v 1.6 2005/02/08 12:56:48 claudio Exp $ */ +/* $OpenBSD: rde_lsdb.c,v 1.7 2005/02/09 20:40:23 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -224,7 +224,7 @@ lsa_check(struct rde_nbr *nbr, struct lsa *lsa, u_int16_t len) } /* MaxAge handling */ - if (ntohs(lsa->hdr.age) == MAX_AGE && lsa_find(area, + if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(area, lsa->hdr.type, lsa->hdr.ls_id, lsa->hdr.adv_rtr) == NULL && !rde_nbr_loading(area)) { /* @@ -466,7 +466,7 @@ lsa_timeout(int fd, short event, void *bula) log_debug("lsa_timeout: REFLOOD"); - if (v->nbr->self) + if (v->nbr->self && v->lsa->hdr.age != htons(MAX_AGE)) lsa_refresh(v); rde_imsg_compose_ospfe(IMSG_LS_FLOOD, v->nbr->peerid, 0, @@ -481,7 +481,7 @@ lsa_refresh(struct vertex *v) u_int16_t len; /* refresh LSA by increasing sequence number by one */ - v->lsa->hdr.age = ntohs(DEFAULT_AGE); + v->lsa->hdr.age = htons(DEFAULT_AGE); seqnum = ntohl(v->lsa->hdr.seq_num); if (seqnum++ == MAX_SEQ_NUM) /* XXX fix me */ @@ -493,8 +493,37 @@ lsa_refresh(struct vertex *v) v->lsa->hdr.ls_chksum = 0; v->lsa->hdr.ls_chksum = htons(iso_cksum(v->lsa, len, LS_CKSUM_OFFSET)); - v->changed = time(NULL); + v->changed = v->stamp = time(NULL); timerclear(&tv); tv.tv_sec = LS_REFRESH_TIME; evtimer_add(&v->ev, &tv); } + +void +lsa_merge(struct rde_nbr *nbr, struct lsa *lsa, struct vertex *v) +{ + struct timeval tv; + time_t now; + + if (v == NULL) { + lsa_add(nbr, lsa); + rde_imsg_compose_ospfe(IMSG_LS_FLOOD, nbr->peerid, 0, + lsa, ntohs(lsa->hdr.len)); + return; + } + + /* TODO check for changes */ + + /* set the seq_num to the current on. lsa_refresh() will do the ++ */ + lsa->hdr.seq_num = v->lsa->hdr.seq_num; + /* overwrite the lsa all other fields are unaffected */ + free(v->lsa); + v->lsa = lsa; + + /* set correct timeout for reflooding the LSA */ + now = time(NULL); + timerclear(&tv); + if (v->changed + MIN_LS_ARRIVAL >= now) + tv.tv_sec = MIN_LS_ARRIVAL; + evtimer_add(&v->ev, &tv); +} |