Commit 48e5f32d authored by Ondřej Zajíček's avatar Ondřej Zajíček

Many changes in I/O and OSPF sockets and packet handling.

I/O:
 - BSD: specify src addr on IP sockets by IP_HDRINCL
 - BSD: specify src addr on UDP sockets by IP_SENDSRCADDR
 - Linux: specify src addr on IP/UDP sockets by IP_PKTINFO
 - IPv6: specify src addr on IP/UDP sockets by IPV6_PKTINFO
 - Alternative SKF_BIND flag for binding to IP address
 - Allows IP/UDP sockets without tx_hook, on these
   sockets a packet is discarded when TX queue is full
 - Use consistently SOL_ for socket layer values.

OSPF:
 - Packet src addr is always explicitly set
 - Support for secondary addresses in BSD
 - Dynamic RX/TX buffers
 - Fixes some minor buffer overruns
 - Interface option 'tx length'
 - Names for vlink pseudoifaces (vlinkX)
 - Vlinks use separate socket for TX
 - Vlinks do not use fixed associated iface
 - Fixes TTL for direct unicast packets
 - Fixes DONTROUTE for OSPF sockets
 - Use ifa->ifname instead of ifa->iface->name
parent f48fa142
...@@ -2212,7 +2212,9 @@ protocol ospf <name> { ...@@ -2212,7 +2212,9 @@ protocol ospf <name> {
wait <num>; wait <num>;
dead count <num>; dead count <num>;
dead <num>; dead <num>;
secondary <switch>;
rx buffer [normal|large|<num>]; rx buffer [normal|large|<num>];
tx length <num>;
type [broadcast|bcast|pointopoint|ptp| type [broadcast|bcast|pointopoint|ptp|
nonbroadcast|nbma|pointomultipoint|ptmp]; nonbroadcast|nbma|pointomultipoint|ptmp];
strict nonbroadcast <switch>; strict nonbroadcast <switch>;
...@@ -2419,12 +2421,32 @@ protocol ospf <name> { ...@@ -2419,12 +2421,32 @@ protocol ospf <name> {
<tag>dead <M>num</M></tag> <tag>dead <M>num</M></tag>
When the router does not receive any messages from a neighbor in When the router does not receive any messages from a neighbor in
<m/dead/ seconds, it will consider the neighbor down. If both directives <m/dead/ seconds, it will consider the neighbor down. If both directives
<m/dead count/ and <m/dead/ are used, <m/dead/ has precendence. <cf/dead count/ and <cf/dead/ are used, <cf/dead/ has precendence.
<tag>secondary <M>switch</M></tag>
On BSD systems, older versions of BIRD supported OSPFv2 only for the
primary IP address of an interface, other IP ranges on the interface
were handled as stub networks. Since v1.4.1, regular operation on
secondary IP addresses is supported, but disabled by default for
compatibility. This option allows to enable it. The option is a
transitional measure, will be removed in the next major release as the
behavior will be changed. On Linux systems, the option is irrelevant, as
operation on non-primary addresses is already the regular behavior.
<tag>rx buffer <M>num</M></tag> <tag>rx buffer <M>num</M></tag>
This sets the size of buffer used for receiving packets. The buffer should This option allows to specify the size of buffers used for packet
be bigger than maximal size of any packets. Value NORMAL (default) processing. The buffer size should be bigger than maximal size of any
means 2*MTU, value LARGE means maximal allowed packet - 65535. packets. By default, buffers are dynamically resized as needed, but a
fixed value could be specified. Value <cf/large/ means maximal allowed
packet size - 65535.
<tag>tx length <M>num</M></tag>
Transmitted OSPF messages that contain large amount of information are
segmented to separate OSPF packets to avoid IP fragmentation. This
option specifies the soft ceiling for the length of generated OSPF
packets. Default value is the MTU of the network interface. Note that
larger OSPF packets may still be generated if underlying OSPF messages
cannot be splitted (e.g. when one large LSA is propagated).
<tag>type broadcast|bcast</tag> <tag>type broadcast|bcast</tag>
BIRD detects a type of a connected network automatically, but BIRD detects a type of a connected network automatically, but
......
...@@ -157,13 +157,13 @@ rfree(void *res) ...@@ -157,13 +157,13 @@ rfree(void *res)
{ {
resource *r = res; resource *r = res;
if (r) if (!r)
{ return;
if (r->n.next)
rem_node(&r->n); if (r->n.next)
r->class->free(r); rem_node(&r->n);
xfree(r); r->class->free(r);
} xfree(r);
} }
/** /**
...@@ -408,6 +408,9 @@ mb_realloc(void *m, unsigned size) ...@@ -408,6 +408,9 @@ mb_realloc(void *m, unsigned size)
void void
mb_free(void *m) mb_free(void *m)
{ {
if (!m)
return;
struct mblock *b = SKIP_BACK(struct mblock, data, m); struct mblock *b = SKIP_BACK(struct mblock, data, m);
rfree(b); rfree(b);
} }
......
...@@ -57,6 +57,9 @@ int sk_open(sock *); /* Open socket */ ...@@ -57,6 +57,9 @@ int sk_open(sock *); /* Open socket */
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */ int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */ int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */ void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */
void sk_set_rbsize(sock *s, uint val); /* Resize RX buffer */
void sk_set_tbsize(sock *s, uint val); /* Resize TX buffer, keeping content */
void sk_set_tbuf(sock *s, void *tbuf); /* Switch TX buffer, NULL-> return to internal */
void sk_dump_all(void); void sk_dump_all(void);
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */ int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */ int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
...@@ -89,10 +92,13 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul ...@@ -89,10 +92,13 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul
#define SKF_V6ONLY 1 /* Use IPV6_V6ONLY socket option */ #define SKF_V6ONLY 1 /* Use IPV6_V6ONLY socket option */
#define SKF_LADDR_RX 2 /* Report local address for RX packets */ #define SKF_LADDR_RX 2 /* Report local address for RX packets */
#define SKF_LADDR_TX 4 /* Allow to specify local address for TX packets */ #define SKF_TTL_RX 4 /* Report TTL / Hop Limit for RX packets */
#define SKF_TTL_RX 8 /* Report TTL / Hop Limit for RX packets */ #define SKF_BIND 8 /* Bind datagram socket to given source address */
#define SKF_THREAD 0x100 /* Socked used in thread, Do not add to main loop */ #define SKF_THREAD 0x100 /* Socked used in thread, Do not add to main loop */
#define SKF_TRUNCATED 0x200 /* Received packet was truncated, set by IO layer */
#define SKF_HDRINCL 0x400 /* Used internally */
#define SKF_PKTINFO 0x800 /* Used internally */
/* /*
* Socket types SA SP DA DP IF TTL SendTo (?=may, -=must not, *=must) * Socket types SA SP DA DP IF TTL SendTo (?=may, -=must not, *=must)
...@@ -118,6 +124,14 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul ...@@ -118,6 +124,14 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul
* call sk_setup_multicast() to enable multicast on that socket, * call sk_setup_multicast() to enable multicast on that socket,
* and then use sk_join_group() and sk_leave_group() to manage * and then use sk_join_group() and sk_leave_group() to manage
* a set of received multicast groups. * a set of received multicast groups.
*
* For datagram (SK_UDP, SK_IP) sockets, there are two ways to handle
* source address. The socket could be bound to it using bind()
* syscall, but that also forbids the reception of multicast packets,
* or the address could be set on per-packet basis using platform
* dependent options (but these are not available in some corner
* cases). The first way is used when SKF_BIND is specified, the
* second way is used otherwise.
*/ */
#endif #endif
...@@ -230,7 +230,7 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa) ...@@ -230,7 +230,7 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
sk->tos = IP_PREC_INTERNET_CONTROL; sk->tos = IP_PREC_INTERNET_CONTROL;
sk->priority = sk_priority_control; sk->priority = sk_priority_control;
sk->ttl = ifa ? 255 : -1; sk->ttl = ifa ? 255 : -1;
sk->flags = SKF_THREAD; sk->flags = SKF_THREAD | SKF_BIND;
#ifdef IPV6 #ifdef IPV6
sk->flags |= SKF_V6ONLY; sk->flags |= SKF_V6ONLY;
......
...@@ -131,7 +131,8 @@ CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC, TTL, SECURITY) ...@@ -131,7 +131,8 @@ CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC, TTL, SECURITY)
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK, ONLY, BFD) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK, ONLY, BFD)
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL) CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY) CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY) CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH)
CF_KEYWORDS(SECONDARY)
%type <t> opttext %type <t> opttext
%type <ld> lsadb_args %type <ld> lsadb_args
...@@ -302,14 +303,16 @@ ospf_iface_item: ...@@ -302,14 +303,16 @@ ospf_iface_item:
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; } | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; } | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; } | AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT ; }
| RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; } | RX BUFFER NORMAL { OSPF_PATT->rx_buffer = 0; }
| RX BUFFER NORMAL { OSPF_PATT->rxbuf = OSPF_RXBUF_NORMAL ; } | RX BUFFER LARGE { OSPF_PATT->rx_buffer = OSPF_MAX_PKT_SIZE; }
| RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if (($3 < OSPF_RXBUF_MINSIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); } | RX BUFFER expr { OSPF_PATT->rx_buffer = $3; if (($3 < OSPF_MIN_PKT_SIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
| TX tos { OSPF_PATT->tx_tos = $2; } | TX tos { OSPF_PATT->tx_tos = $2; }
| TX PRIORITY expr { OSPF_PATT->tx_priority = $3; } | TX PRIORITY expr { OSPF_PATT->tx_priority = $3; }
| TX LENGTH expr { OSPF_PATT->tx_length = $3; if (($3 < OSPF_MIN_PKT_SIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("TX length must be in range 256-65535"); }
| TTL SECURITY bool { OSPF_PATT->ttl_security = $3; } | TTL SECURITY bool { OSPF_PATT->ttl_security = $3; }
| TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; } | TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; }
| BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); } | BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); }
| SECONDARY bool { OSPF_PATT->bsd_secondary = $2; }
| password_list | password_list
; ;
......
...@@ -103,7 +103,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next) ...@@ -103,7 +103,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
length = sizeof(struct ospf_dbdes_packet); length = sizeof(struct ospf_dbdes_packet);
op->length = htons(length); op->length = htons(length);
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name); OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->ifname);
ospf_send_to(ifa, n->ip); ospf_send_to(ifa, n->ip);
break; break;
...@@ -115,7 +115,14 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next) ...@@ -115,7 +115,14 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
snode *sn; snode *sn;
struct ospf_lsa_header *lsa; struct ospf_lsa_header *lsa;
pkt = n->ldbdes; if (n->ldd_bsize != ifa->tx_length)
{
mb_free(n->ldd_buffer);
n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
n->ldd_bsize = ifa->tx_length;
}
pkt = n->ldd_buffer;
op = (struct ospf_packet *) pkt; op = (struct ospf_packet *) pkt;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P); ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
...@@ -124,7 +131,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next) ...@@ -124,7 +131,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
pkt->options = hton_opt(oa->options); pkt->options = hton_opt(oa->options);
j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */ j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */
lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet)); lsa = (n->ldd_buffer + sizeof(struct ospf_dbdes_packet));
if (n->myimms.bit.m) if (n->myimms.bit.m)
{ {
...@@ -175,7 +182,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next) ...@@ -175,7 +182,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
case NEIGHBOR_LOADING: case NEIGHBOR_LOADING:
case NEIGHBOR_FULL: case NEIGHBOR_FULL:
length = ntohs(((struct ospf_packet *) n->ldbdes)->length); length = n->ldd_buffer ? ntohs(((struct ospf_packet *) n->ldd_buffer)->length) : 0;
if (!length) if (!length)
{ {
...@@ -184,12 +191,13 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next) ...@@ -184,12 +191,13 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
return; return;
} }
/* Copy last sent packet again */ /* Send last packet from ldd buffer */
pkt = ospf_tx_buffer(ifa);
memcpy(pkt, n->ldbdes, length);
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name); OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer, "DBDES packet sent to %I via %s", n->ip, ifa->ifname);
sk_set_tbuf(ifa->sk, n->ldd_buffer);
ospf_send_to(ifa, n->ip); ospf_send_to(ifa, n->ip);
sk_set_tbuf(ifa->sk, NULL);
if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */ if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
...@@ -262,7 +270,7 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -262,7 +270,7 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
u32 ps_options = ntoh_opt(ps->options); u32 ps_options = ntoh_opt(ps->options);
u16 ps_iface_mtu = ntohs(ps->iface_mtu); u16 ps_iface_mtu = ntohs(ps->iface_mtu);
OSPF_PACKET(ospf_dump_dbdes, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name); OSPF_PACKET(ospf_dump_dbdes, ps, "DBDES packet received from %I via %s", n->ip, ifa->ifname);
ospf_neigh_sm(n, INM_HELLOREC); ospf_neigh_sm(n, INM_HELLOREC);
...@@ -279,10 +287,10 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -279,10 +287,10 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
return; return;
case NEIGHBOR_EXSTART: case NEIGHBOR_EXSTART:
if ((ps_iface_mtu != ifa->iface->mtu) && (ifa->type != OSPF_IT_VLINK) if ((ifa->type != OSPF_IT_VLINK) && (ps_iface_mtu != ifa->iface->mtu)
&& (ps_iface_mtu != 0) && (ifa->iface->mtu != 0)) && (ps_iface_mtu != 0) && (ifa->iface->mtu != 0))
log(L_WARN "OSPF: MTU mismatch with neighbour %I on interface %s (remote %d, local %d)", log(L_WARN "OSPF: MTU mismatch with neighbour %I on interface %s (remote %d, local %d)",
n->ip, ifa->iface->name, ps_iface_mtu, ifa->iface->mtu); n->ip, ifa->ifname, ps_iface_mtu, ifa->iface->mtu);
if ((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i) if ((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i)
&& (n->rid > po->router_id) && (size == sizeof(struct ospf_dbdes_packet))) && (n->rid > po->router_id) && (size == sizeof(struct ospf_dbdes_packet)))
...@@ -361,8 +369,8 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -361,8 +369,8 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
{ {
if (ps_ddseq != n->dds) /* MASTER */ if (ps_ddseq != n->dds) /* MASTER */
{ {
OSPF_TRACE(D_PACKETS, OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)",
"dbdes - sequence mismatch neighbor %I (master)", n->ip); n->ip);
ospf_neigh_sm(n, INM_SEQMIS); ospf_neigh_sm(n, INM_SEQMIS);
break; break;
} }
...@@ -383,8 +391,7 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -383,8 +391,7 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
{ {
if (ps_ddseq != (n->dds + 1)) /* SLAVE */ if (ps_ddseq != (n->dds + 1)) /* SLAVE */
{ {
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip);
n->ip);
ospf_neigh_sm(n, INM_SEQMIS); ospf_neigh_sm(n, INM_SEQMIS);
break; break;
} }
......
...@@ -61,8 +61,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -61,8 +61,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
struct ospf_hello_packet *ps = (void *) ps_i; struct ospf_hello_packet *ps = (void *) ps_i;
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr, OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s", faddr, ifa->ifname);
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
#ifdef OSPFv2 #ifdef OSPFv2
ip_addr mask = ps->netmask; ip_addr mask = ps->netmask;
...@@ -120,8 +119,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -120,8 +119,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
if (!nn && ifa->strictnbma) if (!nn && ifa->strictnbma)
{ {
log(L_WARN "Ignoring new neighbor: %I on %s", faddr, log(L_WARN "Ignoring new neighbor: %I on %s", faddr, ifa->ifname);
ifa->iface->name);
return; return;
} }
...@@ -129,8 +127,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -129,8 +127,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
(((ps->priority == 0) && nn->eligible) || (((ps->priority == 0) && nn->eligible) ||
((ps->priority > 0) && !nn->eligible))) ((ps->priority > 0) && !nn->eligible)))
{ {
log(L_ERR "Eligibility mismatch for neighbor: %I on %s", log(L_ERR "Eligibility mismatch for neighbor: %I on %s", faddr, ifa->ifname);
faddr, ifa->iface->name);
return; return;
} }
...@@ -138,8 +135,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -138,8 +135,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
nn->found = 1; nn->found = 1;
} }
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname);
ifa->iface->name);
n = ospf_neighbor_new(ifa); n = ospf_neighbor_new(ifa);
...@@ -263,7 +259,7 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn) ...@@ -263,7 +259,7 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
p = (struct proto *) (ifa->oa->po); p = (struct proto *) (ifa->oa->po);
DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n", DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n",
p->name, ifa->iface->name, ifa->addr->ip); p->name, ifa->ifname, ifa->addr->ip);
/* Now we should send a hello packet */ /* Now we should send a hello packet */
pkt = ospf_tx_buffer(ifa); pkt = ospf_tx_buffer(ifa);
...@@ -309,9 +305,9 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn) ...@@ -309,9 +305,9 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
u32 *pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet)); u32 *pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet));
WALK_LIST(neigh, ifa->neigh_list) WALK_LIST(neigh, ifa->neigh_list)
{ {
if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_bufsize(ifa)) if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_maxsize(ifa))
{ {
log(L_WARN "%s: Too many neighbors on interface %s", p->name, ifa->iface->name); log(L_WARN "%s: Too many neighbors on interface %s", p->name, ifa->ifname);
break; break;
} }
*(pp + i) = htonl(neigh->rid); *(pp + i) = htonl(neigh->rid);
...@@ -376,6 +372,5 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn) ...@@ -376,6 +372,5 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
bug("Bug in ospf_hello_send()"); bug("Bug in ospf_hello_send()");
} }
OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s", OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s", ifa->ifname);
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
} }
This diff is collapsed.
...@@ -17,11 +17,16 @@ void ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface); ...@@ -17,11 +17,16 @@ void ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface);
void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a); void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
void ospf_iface_info(struct ospf_iface *ifa); void ospf_iface_info(struct ospf_iface *ifa);
void ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip); void ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip);
void ospf_iface_new_vlink(struct proto_ospf *po, struct ospf_iface_patt *ip);
void ospf_iface_remove(struct ospf_iface *ifa); void ospf_iface_remove(struct ospf_iface *ifa);
void ospf_iface_shutdown(struct ospf_iface *ifa); void ospf_iface_shutdown(struct ospf_iface *ifa);
int ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new); int ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new);
void ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac); void ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac);
int ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen);
void ospf_open_vlink_sk(struct proto_ospf *po);
struct nbma_node *find_nbma_node_in(list *nnl, ip_addr ip); struct nbma_node *find_nbma_node_in(list *nnl, ip_addr ip);
static inline struct nbma_node * static inline struct nbma_node *
......
...@@ -92,7 +92,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue) ...@@ -92,7 +92,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
op->length = htons(len); op->length = htons(len);
DBG("Sending and continuing! Len=%u\n", len); DBG("Sending and continuing! Len=%u\n", len);
OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name); OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->ifname);
if (ifa->type == OSPF_IT_BCAST) if (ifa->type == OSPF_IT_BCAST)
{ {
...@@ -121,7 +121,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue) ...@@ -121,7 +121,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
op->length = htons(len); op->length = htons(len);
DBG("Sending! Len=%u\n", len); DBG("Sending! Len=%u\n", len);
OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name); OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->ifname);
if (ifa->type == OSPF_IT_BCAST) if (ifa->type == OSPF_IT_BCAST)
{ {
...@@ -153,7 +153,7 @@ ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -153,7 +153,7 @@ ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
} }
struct ospf_lsack_packet *ps = (void *) ps_i; struct ospf_lsack_packet *ps = (void *) ps_i;
OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->iface->name); OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->ifname);
ospf_neigh_sm(n, INM_HELLOREC); ospf_neigh_sm(n, INM_HELLOREC);
......
...@@ -82,7 +82,7 @@ ospf_lsreq_send(struct ospf_neighbor *n) ...@@ -82,7 +82,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
i) * sizeof(struct ospf_lsreq_header); i) * sizeof(struct ospf_lsreq_header);
op->length = htons(length); op->length = htons(length);
OSPF_PACKET(ospf_dump_lsreq, pk, "LSREQ packet sent to %I via %s", n->ip, n->ifa->iface->name); OSPF_PACKET(ospf_dump_lsreq, pk, "LSREQ packet sent to %I via %s", n->ip, n->ifa->ifname);
ospf_send_to(n->ifa, n->ip); ospf_send_to(n->ifa, n->ip);
} }
...@@ -107,7 +107,7 @@ ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -107,7 +107,7 @@ ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
} }
struct ospf_lsreq_packet *ps = (void *) ps_i; struct ospf_lsreq_packet *ps = (void *) ps_i;
OSPF_PACKET(ospf_dump_lsreq, ps, "LSREQ packet received from %I via %s", n->ip, ifa->iface->name); OSPF_PACKET(ospf_dump_lsreq, ps, "LSREQ packet received from %I via %s", n->ip, ifa->ifname);
if (n->state < NEIGHBOR_EXCHANGE) if (n->state < NEIGHBOR_EXCHANGE)
return; return;
......
...@@ -278,22 +278,22 @@ ospf_lsupd_flood(struct proto_ospf *po, ...@@ -278,22 +278,22 @@ ospf_lsupd_flood(struct proto_ospf *po,
struct ospf_packet *op; struct ospf_packet *op;
struct ospf_lsa_header *lh; struct ospf_lsa_header *lh;
pk = ospf_tx_buffer(ifa);
op = &pk->ospf_packet;
ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
pk->lsano = htonl(1);
/* Check iface buffer size */ /* Check iface buffer size */
int len2 = sizeof(struct ospf_lsupd_packet) + (hn ? ntohs(hn->length) : hh->length); uint len2 = sizeof(struct ospf_lsupd_packet) + (hn ? ntohs(hn->length) : hh->length);
if (len2 > ospf_pkt_bufsize(ifa)) if (ospf_iface_assure_bufsize(ifa, len2) < 0)
{ {
/* Cannot fit in a tx buffer, skip that iface */ /* Cannot fit in a tx buffer, skip that iface */
log(L_ERR "OSPF: LSA too large to flood on %s (Type: %04x, Id: %R, Rt: %R)", log(L_ERR "OSPF: LSA too large to flood on %s (Type: %04x, Id: %R, Rt: %R)",
ifa->iface->name, hh->type, hh->id, hh->rt); ifa->ifname, hh->type, hh->id, hh->rt);
continue; continue;
} }
pk = ospf_tx_buffer(ifa);
op = &pk->ospf_packet;
ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
pk->lsano = htonl(1);
lh = (struct ospf_lsa_header *) (pk + 1); lh = (struct ospf_lsa_header *) (pk + 1);
/* Copy LSA into the packet */ /* Copy LSA into the packet */
...@@ -322,7 +322,7 @@ ospf_lsupd_flood(struct proto_ospf *po, ...@@ -322,7 +322,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
op->length = htons(len); op->length = htons(len);
OSPF_PACKET(ospf_dump_lsupd, pk, "LSUPD packet flooded via %s", ifa->iface->name); OSPF_PACKET(ospf_dump_lsupd, pk, "LSUPD packet flooded via %s", ifa->ifname);
switch (ifa->type) switch (ifa->type)
{ {
...@@ -406,7 +406,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l) ...@@ -406,7 +406,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
break; break;
/* LSA is larger than MTU, check buffer size */ /* LSA is larger than MTU, check buffer size */
if (len2 > ospf_pkt_bufsize(n->ifa)) if (ospf_iface_assure_bufsize(n->ifa, len2) < 0)
{ {
/* Cannot fit in a tx buffer, skip that */ /* Cannot fit in a tx buffer, skip that */
log(L_ERR "OSPF: LSA too large to send (Type: %04x, Id: %R, Rt: %R)", log(L_ERR "OSPF: LSA too large to send (Type: %04x, Id: %R, Rt: %R)",
...@@ -414,6 +414,10 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l) ...@@ -414,6 +414,10 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
lsr = NODE_NEXT(lsr); lsr = NODE_NEXT(lsr);
continue; continue;
} }
/* TX buffer could be reallocated */
pkt = ospf_tx_buffer(n->ifa);
buf = (void *) pkt;
} }
/* Copy the LSA to the packet */ /* Copy the LSA to the packet */
...@@ -432,7 +436,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l) ...@@ -432,7 +436,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
pkt->lsano = htonl(lsano); pkt->lsano = htonl(lsano);
pkt->ospf_packet.length = htons(len); pkt->ospf_packet.length = htons(len);
OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet sent to %I via %s", OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet sent to %I via %s",
n->ip, n->ifa->iface->name); n->ip, n->ifa->ifname);
ospf_send_to(n->ifa, n->ip); ospf_send_to(n->ifa, n->ip);
} }
} }
...@@ -455,7 +459,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, ...@@ -455,7 +459,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
} }
struct ospf_lsupd_packet *ps = (void *) ps_i; struct ospf_lsupd_packet *ps = (void *) ps_i;
OSPF_PACKET(ospf_dump_lsupd, ps, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name); OSPF_PACKET(ospf_dump_lsupd, ps, "LSUPD packet received from %I via %s", n->ip, ifa->ifname);
if (n->state < NEIGHBOR_EXCHANGE) if (n->state < NEIGHBOR_EXCHANGE)
{ {
......
...@@ -69,7 +69,6 @@ ospf_neighbor_new(struct ospf_iface *ifa) ...@@ -69,7 +69,6 @@ ospf_neighbor_new(struct ospf_iface *ifa)
add_tail(&ifa->neigh_list, NODE n); add_tail(&ifa->neigh_list, NODE n);
n->adj = 0; n->adj = 0;
n->csn = 0; n->csn = 0;
n->ldbdes = mb_allocz(pool, ifa->iface->mtu);
n->state = NEIGHBOR_DOWN; n->state = NEIGHBOR_DOWN;
init_lists(n); init_lists(n);
...@@ -286,10 +285,10 @@ can_do_adj(struct ospf_neighbor *n) ...@@ -286,10 +285,10 @@ can_do_adj(struct ospf_neighbor *n)
{ {
case OSPF_IS_DOWN: case OSPF_IS_DOWN:
case OSPF_IS_LOOP: case OSPF_IS_LOOP:
bug("%s: Iface %s in down state?", p->name, ifa->iface->name); bug("%s: Iface %s in down state?", p->name, ifa->ifname);
break; break;
case OSPF_IS_WAITING: case OSPF_IS_WAITING:
DBG("%s: Neighbor? on iface %s\n", p->name, ifa->iface->name); DBG("%s: Neighbor? on iface %s\n", p->name, ifa->ifname);
break; break;
case OSPF_IS_DROTHER: case OSPF_IS_DROTHER:
if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid)) if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
...@@ -303,15 +302,15 @@ can_do_adj(struct ospf_neighbor *n) ...@@ -303,15 +302,15 @@ can_do_adj(struct ospf_neighbor *n)
i = 1; i = 1;
break; break;
default: default:
bug("%s: Iface %s in unknown state?", p->name, ifa->iface->name); bug("%s: Iface %s in unknown state?", p->name, ifa->ifname);
break; break;
} }
break; break;
default: default:
bug("%s: Iface %s is unknown type?", p->name, ifa->iface->name); bug("%s: Iface %s is unknown type?", p->name, ifa->ifname);
break; break;
} }
DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->iface->name, i); DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->ifname, i);
return i; return i;
} }
...@@ -556,9 +555,8 @@ neighbor_timer_hook(timer * timer) ...@@ -556,9 +555,8 @@ neighbor_timer_hook(timer * timer)
struct ospf_iface *ifa = n->ifa; struct ospf_iface *ifa = n->ifa;
struct proto *p = &ifa->oa->po->proto; struct proto *p = &ifa->oa->po->proto;
OSPF_TRACE(D_EVENTS, OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I.",
"Inactivity timer fired on interface %s for neighbor %I.", ifa->ifname, n->ip);
ifa->iface->name, n->ip);
ospf_neigh_remove(n); ospf_neigh_remove(n);