From 94c42054ea65d10477afc76f221e3ac345a431eb Mon Sep 17 00:00:00 2001 From: Ondrej Filip Date: Tue, 15 Mar 2005 22:06:36 +0000 Subject: Added new parametr 'rx buffer '. BIRD is able to receive very large packets (if configured). --- doc/bird.conf.example | 1 + doc/bird.sgml | 6 ++++ proto/ospf/config.Y | 4 +++ proto/ospf/iface.c | 97 +++++++++++++++++++++++++++++++-------------------- proto/ospf/iface.h | 6 +++- proto/ospf/ospf.c | 12 ++++++- proto/ospf/ospf.h | 15 ++++---- 7 files changed, 94 insertions(+), 47 deletions(-) diff --git a/doc/bird.conf.example b/doc/bird.conf.example index 8260c02..05259d5 100644 --- a/doc/bird.conf.example +++ b/doc/bird.conf.example @@ -120,6 +120,7 @@ protocol static { # password "pass"; # }; # interface "arc0" { +# rx buffer large; # type nonbroadcast; # poll 14; # dead 75; diff --git a/doc/bird.sgml b/doc/bird.sgml index fa7aabb..87113fa 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1026,6 +1026,7 @@ protocol ospf <name> { wait <num>; dead count <num>; dead <num>; + rx buffer [normal|large|<num>]; type [broadcast|nonbroadcast|pointopoint]; strict nonbroadcast <switch>; authentication [none|simple]; @@ -1134,6 +1135,11 @@ protocol ospf <name> { rx buffer num + This sets the size of buffer used for receiving packets. The buffer should + be bigger than maximal size of any packets. Value NORMAL (default) + means 2*MTU, value LARGE means maximal allowed packet - 65536. + type broadcast BIRD detects a type of a connected network automatically, but sometimes it's convenient to force use of a different type manually. diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index f14f1a4..0c6a408 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -26,6 +26,7 @@ CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT) CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE) CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, LINK) +CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL) %type opttext @@ -142,6 +143,9 @@ ospf_iface_item: | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; } | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; } | AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; } + | RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; } + | RX BUFFER NORMAL { OSPF_PATT->rxbuf = OSPF_RXBUF_NORMAL ; } + | RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if ($3 < OSPF_RXBUF_MINSIZE) cf_error("Buffer size is too small") ; } | password_list {OSPF_PATT->passwords = (list *) $1; } ; diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 3306285..d5d068b 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -41,6 +41,23 @@ wait_timer_hook(timer * timer) ospf_iface_sm(ifa, ISM_WAITF); } +u32 +rxbufsize(struct ospf_iface *ifa) +{ + switch(ifa->rxbuf) + { + case OSPF_RXBUF_NORMAL: + return (ifa->iface->mtu * 2); + break; + case OSPF_RXBUF_LARGE: + return OSPF_MAX_PKT_SIZE; + break; + default: + return ifa->rxbuf; + break; + } +} + static sock * ospf_open_ip_socket(struct ospf_iface *ifa) { @@ -59,7 +76,7 @@ ospf_open_ip_socket(struct ospf_iface *ifa) ipsk->tx_hook = ospf_tx_hook; ipsk->err_hook = ospf_err_hook; ipsk->iface = ifa->iface; - ipsk->rbsize = OSPF_MAX_PKT_SIZE; + ipsk->rbsize = rxbufsize(ifa); ipsk->tbsize = ifa->iface->mtu; ipsk->data = (void *) ifa; if (sk_open(ipsk) != 0) @@ -126,7 +143,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state) 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 = OSPF_MAX_PKT_SIZE; + ifa->dr_sk->rbsize = rxbufsize(ifa); ifa->dr_sk->tbsize = ifa->iface->mtu; ifa->dr_sk->data = (void *) ifa; if (sk_open(ifa->dr_sk) != 0) @@ -299,7 +316,7 @@ ospf_open_mc_socket(struct ospf_iface *ifa) mcsk->tx_hook = ospf_tx_hook; mcsk->err_hook = ospf_err_hook; mcsk->iface = ifa->iface; - mcsk->rbsize = OSPF_MAX_PKT_SIZE; + mcsk->rbsize = rxbufsize(ifa); mcsk->tbsize = ifa->iface->mtu; mcsk->data = (void *) ifa; if (sk_open(mcsk) != 0) @@ -397,6 +414,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, ifa->stub = ip->stub; ifa->autype = ip->autype; ifa->passwords = ip->passwords; + ifa->rxbuf = ip->rxbuf; if (ip->type == OSPF_IT_UNDEF) ifa->type = ospf_iface_clasify(ifa->iface); @@ -476,6 +494,44 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, olock_acquire(lock); } +void +ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa) +{ + struct proto *p = &po->proto; + struct ospf_packet *op; + struct ospf_neighbor *n; + OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", ifa->iface->name); + if (ifa->hello_sk) + { + ifa->hello_sk->rbsize = rxbufsize(ifa); + ifa->hello_sk->tbsize = ifa->iface->mtu; + sk_reallocate(ifa->hello_sk); + } + if (ifa->dr_sk) + { + ifa->dr_sk->rbsize = rxbufsize(ifa); + ifa->dr_sk->tbsize = ifa->iface->mtu; + sk_reallocate(ifa->dr_sk); + } + if (ifa->ip_sk) + { + ifa->ip_sk->rbsize = rxbufsize(ifa); + ifa->ip_sk->tbsize = ifa->iface->mtu; + sk_reallocate(ifa->ip_sk); + } + + WALK_LIST(n, ifa->neigh_list) + { + op = (struct ospf_packet *) n->ldbdes; + n->ldbdes = mb_allocz(n->pool, ifa->iface->mtu); + + if (ntohs(op->length) <= ifa->iface->mtu) /* If the packet in old buffer is bigger, let it filled by zeros */ + memcpy(n->ldbdes, op, ifa->iface->mtu); /* If the packet is old is same or smaller, copy it */ + + rfree(op); + } +} + void ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface) { @@ -517,40 +573,7 @@ ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface) if (flags & IF_CHANGE_MTU) { if ((ifa = ospf_iface_find((struct proto_ospf *) p, iface)) != NULL) - { - struct ospf_packet *op; - struct ospf_neighbor *n; - OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", iface->name); - if (ifa->hello_sk) - { - ifa->hello_sk->rbsize = OSPF_MAX_PKT_SIZE; - ifa->hello_sk->tbsize = ifa->iface->mtu; - sk_reallocate(ifa->hello_sk); - } - if (ifa->dr_sk) - { - ifa->dr_sk->rbsize = OSPF_MAX_PKT_SIZE; - ifa->dr_sk->tbsize = ifa->iface->mtu; - sk_reallocate(ifa->dr_sk); - } - if (ifa->ip_sk) - { - ifa->ip_sk->rbsize = OSPF_MAX_PKT_SIZE; - ifa->ip_sk->tbsize = ifa->iface->mtu; - sk_reallocate(ifa->ip_sk); - } - - WALK_LIST(n, ifa->neigh_list) - { - op = (struct ospf_packet *) n->ldbdes; - n->ldbdes = mb_allocz(n->pool, iface->mtu); - - if (ntohs(op->length) <= iface->mtu) /* If the packet in old buffer is bigger, let it filled by zeros */ - memcpy(n->ldbdes, op, iface->mtu); /* If the packet is old is same or smaller, copy it */ - - rfree(op); - } - } + ospf_iface_change_mtu(po, ifa); } } diff --git a/proto/ospf/iface.h b/proto/ospf/iface.h index 556024b..55c64bf 100644 --- a/proto/ospf/iface.h +++ b/proto/ospf/iface.h @@ -1,7 +1,7 @@ /* * BIRD -- OSPF * - * (c) 1999 - 2004 Ondrej Filip + * (c) 1999--2005 Ondrej Filip * * Can be freely distributed and used under the terms of the GNU GPL. * @@ -17,5 +17,9 @@ void ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface); void ospf_iface_info(struct ospf_iface *ifa); void ospf_iface_shutdown(struct ospf_iface *ifa); void ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_config *ac, struct ospf_iface_patt *ip); +void ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa); +void ospf_set_rxbuf_size(struct ospf_iface *ifa, u32 rxbuf); + + #endif /* _BIRD_OSPF_IFACE_H_ */ diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index f66dbad..b382df0 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -637,7 +637,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c) { /* Now reconfigure interface */ if (!(newip = (struct ospf_iface_patt *) - iface_patt_match(&oldac->patt_list, ifa->iface))) + iface_patt_match(&newac->patt_list, ifa->iface))) return 0; /* HELLO TIMER */ @@ -672,6 +672,16 @@ ospf_reconfigure(struct proto *p, struct proto_config *c) schedule_rt_lsa(ifa->oa); } + /* RX BUFF */ + if (oldip->rxbuf != newip->rxbuf) + { + ifa->rxbuf = newip->rxbuf; + OSPF_TRACE(D_EVENTS, + "Changing rxbuf interface %s from %d to %d", + ifa->iface->name, oldip->rxbuf, newip->rxbuf); + ospf_iface_change_mtu(po, ifa); + } + /* strict nbma */ if ((oldip->strictnbma == 0) && (newip->strictnbma != 0)) { diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 1bb7f87..fcefa81 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -11,19 +11,13 @@ #define MAXNETS 10 #define OSPF_VLINK_MTU 576 /* RFC2328 - A.1 */ -#undef OSPF_BIG_PACKETS /* +#define OSPF_MAX_PKT_SIZE 65536 + /* * RFC 2328 says, maximum packet size is 65535 * This could be too much for small systems, so I * normally allocate 2*mtu - (I found one cisco * sending packets mtu+16) */ - -#ifdef OSPF_BIG_PACKETS -#define OSPF_MAX_PKT_SIZE 65536 -#else -#define OSPF_MAX_PKT_SIZE (ifa->iface->mtu * 2) -#endif - #ifdef LOCAL_DEBUG #define OSPF_FORCE_DEBUG 1 #else @@ -206,6 +200,7 @@ struct ospf_iface list nbma_list; u8 priority; /* A router priority for DR election */ u8 ioprob; + u32 rxbuf; }; struct ospf_md5 @@ -572,6 +567,10 @@ struct ospf_iface_patt #define OSPF_AUTH_SIMPLE 1 #define OSPF_AUTH_CRYPT 2 #define OSPF_AUTH_CRYPT_SIZE 16 + u32 rxbuf; +#define OSPF_RXBUF_NORMAL 0 +#define OSPF_RXBUF_LARGE 1 +#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */ list *passwords; list nbma_list; }; -- cgit v1.2.3