diff options
-rw-r--r-- | proto/ospf/config.Y | 20 | ||||
-rw-r--r-- | proto/ospf/hello.c | 80 | ||||
-rw-r--r-- | proto/ospf/iface.c | 31 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 7 |
4 files changed, 101 insertions, 37 deletions
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 9416612..e678a26 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -16,12 +16,14 @@ CF_DEFINES static struct ospf_area_config *this_area; static struct iface_patt *this_ipatt; #define OSPF_PATT ((struct ospf_iface_patt *) this_ipatt) +static struct nbma_node *this_nbma; CF_DECLS CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG) CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT) CF_KEYWORDS(HELLO, TRANSIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE) +CF_KEYWORDS(NEIGHBORS) %type <t> opttext @@ -83,8 +85,23 @@ ospf_iface_item: | TYPE BROADCAST { OSPF_PATT->type = OSPF_IT_BCAST ; } | TYPE NONBROADCAST { OSPF_PATT->type = OSPF_IT_NBMA ; } | TYPE POINTOPOINT { OSPF_PATT->type = OSPF_IT_PTP ; } - | + | NEIGHBORS '{' ipa_list '}' + | ; + +ipa_list: + /* empty */ + | ipa_list ipa_item + ; + +ipa_item: IPA ';' + { + this_nbma = cfg_allocz(sizeof(struct nbma_node)); + add_tail(&OSPF_PATT->nbma_list, NODE this_nbma); + this_nbma->ip=$1; + } +; + ospf_iface_start: { @@ -98,6 +115,7 @@ ospf_iface_start: OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D; OSPF_PATT->deadc = DEADC_D; OSPF_PATT->type = OSPF_IT_UNDEF; + init_list(&OSPF_PATT->nbma_list); } ; diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 3e4bfff..21cd1ea 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -194,39 +194,69 @@ hello_timer_hook(timer *timer) /* First a common packet header */ if(ifa->type!=OSPF_IT_NBMA) { - /* Now fill ospf_hello header */ pkt=(struct ospf_hello_packet *)(ifa->hello_sk->tbuf); - op=(struct ospf_packet *)pkt; - - fill_ospf_pkt_hdr(ifa, pkt, HELLO_P); - - pkt->netmask=ipa_mkmask(ifa->iface->addr->pxlen); - ipa_hton(pkt->netmask); - pkt->helloint=ntohs(ifa->helloint); - pkt->options=ifa->options; - pkt->priority=ifa->priority; - pkt->deadint=htonl(ifa->deadc*ifa->helloint); - pkt->dr=htonl(ifa->drid); - pkt->bdr=htonl(ifa->bdrid); - - /* Fill all neighbors */ - i=0; - pp=(u32 *)(((u8 *)pkt)+sizeof(struct ospf_hello_packet)); - WALK_LIST (neigh, ifa->neigh_list) - { - *(pp+i)=htonl(neigh->rid); - i++; - } + } + else + { + pkt=(struct ospf_hello_packet *)(ifa->ip_sk->tbuf); + } - length=sizeof(struct ospf_hello_packet)+i*sizeof(u32); - op->length=htons(length); + /* Now fill ospf_hello header */ + op=(struct ospf_packet *)pkt; - ospf_pkt_finalize(ifa, op); + fill_ospf_pkt_hdr(ifa, pkt, HELLO_P); + + pkt->netmask=ipa_mkmask(ifa->iface->addr->pxlen); + ipa_hton(pkt->netmask); + pkt->helloint=ntohs(ifa->helloint); + pkt->options=ifa->options; + pkt->priority=ifa->priority; + pkt->deadint=htonl(ifa->deadc*ifa->helloint); + pkt->dr=htonl(ifa->drid); + pkt->bdr=htonl(ifa->bdrid); + + /* Fill all neighbors */ + i=0; + pp=(u32 *)(((u8 *)pkt)+sizeof(struct ospf_hello_packet)); + WALK_LIST (neigh, ifa->neigh_list) + { + *(pp+i)=htonl(neigh->rid); + i++; + } + + length=sizeof(struct ospf_hello_packet)+i*sizeof(u32); + op->length=htons(length); + + ospf_pkt_finalize(ifa, op); /* And finally send it :-) */ + if(ifa->type!=OSPF_IT_NBMA) + { sk_send(ifa->hello_sk,length); } + else /* NBMA */ + { + list n_list; + struct ospf_neighbor *n1; + struct nbma_node *nb; + int send; + init_list(&n_list); + WALK_LIST(nb,ifa->nbma_list) + { + send=1; + WALK_LIST(n1, ifa->neigh_list) + { + if(ipa_compare(nb->ip,n1->ip)==0) + { + send=0; + break; + } + } + if(send) sk_send_to(ifa->ip_sk, length, nb->ip, OSPF_PROTO); + } + sk_send_to_agt(ifa->ip_sk, length, ifa, NEIGHBOR_DOWN); + } debug("%s: Hello sent via %s\n",p->name,ifa->iface->name); } diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index c0d8770..6435d39 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -33,7 +33,7 @@ iface_chstate(struct ospf_iface *ifa, u8 state) { if((state==OSPF_IS_BACKUP)||(state==OSPF_IS_DR)) { - if(ifa->dr_sk==NULL) + if((ifa->dr_sk==NULL)&&(ifa->type!=OSPF_IT_NBMA)) { DBG("%s: Adding new multicast socket for (B)DR\n", p->name); ifa->dr_sk=sk_new(p->pool); @@ -290,6 +290,7 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface) struct ospf_config *c=(struct ospf_config *)(p->cf); struct ospf_area_config *ac; struct ospf_iface_patt *ip=NULL; + struct nbma_node *nbma,*nb; u8 i; DBG("%s: If notify called\n", p->name); @@ -323,7 +324,7 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface) for(i=0;i<8;i++) ifa->aukey[i]=0; ifa->options=2; /* FIXME what options? */ - if(ip->type=OSPF_IT_UNDEF) + if(ip->type==OSPF_IT_UNDEF) ifa->type=ospf_iface_clasify(ifa->iface, (struct proto *)ifa->proto); else ifa->type=ip->type; @@ -338,18 +339,26 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface) return; } ifa->dr_sk=NULL; + } - if((ifa->ip_sk=ospf_open_ip_socket(ifa))==NULL) - { - log("%s: Huh? could not open ip socket on interface %s?", p->name, - iface->name); - mb_free(ifa); - log("%s: Ignoring this interface", p->name); - return; - } + if((ifa->ip_sk=ospf_open_ip_socket(ifa))==NULL) + { + log("%s: Huh? could not open ip socket on interface %s?", p->name, + iface->name); + mb_free(ifa); + log("%s: Ignoring this interface", p->name); + return; + } - init_list(&(ifa->neigh_list)); + 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)); + nbma->ip=nb->ip; + add_tail(&ifa->nbma_list, NODE nbma); } + /* Add hello timer */ ifa->hello_timer=tm_new(p->pool); ifa->hello_timer->data=ifa; diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index d44db95..6736fa0 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -52,6 +52,11 @@ struct ospf_config { list area_list; }; +struct nbma_node { + node n; + ip_addr ip; +}; + struct ospf_area_config { node n; u32 areaid; @@ -114,6 +119,7 @@ struct ospf_iface { */ struct top_hash_entry *nlsa; /* Originated net lsa */ int fadj; /* Number of full adjacent neigh */ + list nbma_list; }; struct ospf_packet { @@ -369,6 +375,7 @@ struct ospf_iface_patt { int waitint; int deadc; int type; + list nbma_list; }; static int ospf_start(struct proto *p); |