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> {
wait <num>;
dead count <num>;
dead <num>;
secondary <switch>;
rx buffer [normal|large|<num>];
tx length <num>;
type [broadcast|bcast|pointopoint|ptp|
nonbroadcast|nbma|pointomultipoint|ptmp];
strict nonbroadcast <switch>;
......@@ -2419,12 +2421,32 @@ protocol ospf <name> {
<tag>dead <M>num</M></tag>
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 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>
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 - 65535.
This option allows to specify the size of buffers used for packet
processing. The buffer size should be bigger than maximal size of any
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>
BIRD detects a type of a connected network automatically, but
......
......@@ -157,13 +157,13 @@ rfree(void *res)
{
resource *r = res;
if (r)
{
if (r->n.next)
rem_node(&r->n);
r->class->free(r);
xfree(r);
}
if (!r)
return;
if (r->n.next)
rem_node(&r->n);
r->class->free(r);
xfree(r);
}
/**
......@@ -408,6 +408,9 @@ mb_realloc(void *m, unsigned size)
void
mb_free(void *m)
{
if (!m)
return;
struct mblock *b = SKIP_BACK(struct mblock, data, m);
rfree(b);
}
......
......@@ -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_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_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);
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 */
......@@ -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_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 8 /* Report TTL / Hop Limit for RX packets */
#define SKF_TTL_RX 4 /* 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_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)
......@@ -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,
* and then use sk_join_group() and sk_leave_group() to manage
* 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
......@@ -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->priority = sk_priority_control;
sk->ttl = ifa ? 255 : -1;
sk->flags = SKF_THREAD;
sk->flags = SKF_THREAD | SKF_BIND;
#ifdef IPV6
sk->flags |= SKF_V6ONLY;
......
......@@ -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(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
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 <ld> lsadb_args
......@@ -302,14 +303,16 @@ 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) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
| RX BUFFER NORMAL { OSPF_PATT->rx_buffer = 0; }
| RX BUFFER LARGE { OSPF_PATT->rx_buffer = OSPF_MAX_PKT_SIZE; }
| 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 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 TX ONLY { OSPF_PATT->ttl_security = 2; }
| BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); }
| SECONDARY bool { OSPF_PATT->bsd_secondary = $2; }
| password_list
;
......
......@@ -103,7 +103,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
length = sizeof(struct ospf_dbdes_packet);
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);
break;
......@@ -115,7 +115,14 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
snode *sn;
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;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
......@@ -124,7 +131,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
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 */
lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
lsa = (n->ldd_buffer + sizeof(struct ospf_dbdes_packet));
if (n->myimms.bit.m)
{
......@@ -175,7 +182,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
case NEIGHBOR_LOADING:
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)
{
......@@ -184,12 +191,13 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
return;
}
/* Copy last sent packet again */
pkt = ospf_tx_buffer(ifa);
memcpy(pkt, n->ldbdes, length);
/* Send last packet from ldd buffer */
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);
sk_set_tbuf(ifa->sk, NULL);
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,
u32 ps_options = ntoh_opt(ps->options);
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);
......@@ -279,10 +287,10 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
return;
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))
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)
&& (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,
{
if (ps_ddseq != n->dds) /* MASTER */
{
OSPF_TRACE(D_PACKETS,
"dbdes - sequence mismatch neighbor %I (master)", n->ip);
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)",
n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
......@@ -383,8 +391,7 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
{
if (ps_ddseq != (n->dds + 1)) /* SLAVE */
{
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)",
n->ip);
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
......
......@@ -61,8 +61,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
struct ospf_hello_packet *ps = (void *) ps_i;
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s", faddr, ifa->ifname);
#ifdef OSPFv2
ip_addr mask = ps->netmask;
......@@ -120,8 +119,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
if (!nn && ifa->strictnbma)
{
log(L_WARN "Ignoring new neighbor: %I on %s", faddr,
ifa->iface->name);
log(L_WARN "Ignoring new neighbor: %I on %s", faddr, ifa->ifname);
return;
}
......@@ -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)))
{
log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
faddr, ifa->iface->name);
log(L_ERR "Eligibility mismatch for neighbor: %I on %s", faddr, ifa->ifname);
return;
}
......@@ -138,8 +135,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
nn->found = 1;
}
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr,
ifa->iface->name);
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname);
n = ospf_neighbor_new(ifa);
......@@ -263,7 +259,7 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
p = (struct proto *) (ifa->oa->po);
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 */
pkt = ospf_tx_buffer(ifa);
......@@ -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));
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;
}
*(pp + i) = htonl(neigh->rid);
......@@ -376,6 +372,5 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
bug("Bug in ospf_hello_send()");
}
OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s",
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s", ifa->ifname);
}
This diff is collapsed.
......@@ -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_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_vlink(struct proto_ospf *po, struct ospf_iface_patt *ip);
void ospf_iface_remove(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);
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);
static inline struct nbma_node *
......
......@@ -92,7 +92,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
op->length = htons(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)
{
......@@ -121,7 +121,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
op->length = htons(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)
{
......@@ -153,7 +153,7 @@ ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
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);
......
......@@ -82,7 +82,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
i) * sizeof(struct ospf_lsreq_header);
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);
}
......@@ -107,7 +107,7 @@ ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
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)
return;
......
......@@ -278,22 +278,22 @@ ospf_lsupd_flood(struct proto_ospf *po,
struct ospf_packet *op;
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 */
int len2 = sizeof(struct ospf_lsupd_packet) + (hn ? ntohs(hn->length) : hh->length);
if (len2 > ospf_pkt_bufsize(ifa))
uint len2 = sizeof(struct ospf_lsupd_packet) + (hn ? ntohs(hn->length) : hh->length);
if (ospf_iface_assure_bufsize(ifa, len2) < 0)
{
/* 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)",
ifa->iface->name, hh->type, hh->id, hh->rt);
ifa->ifname, hh->type, hh->id, hh->rt);
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);
/* Copy LSA into the packet */
......@@ -322,7 +322,7 @@ ospf_lsupd_flood(struct proto_ospf *po,
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)
{
......@@ -406,7 +406,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
break;
/* 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 */
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)
lsr = NODE_NEXT(lsr);
continue;
}
/* TX buffer could be reallocated */
pkt = ospf_tx_buffer(n->ifa);
buf = (void *) pkt;
}
/* Copy the LSA to the packet */
......@@ -432,7 +436,7 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
pkt->lsano = htonl(lsano);
pkt->ospf_packet.length = htons(len);
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);
}
}
......@@ -455,7 +459,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
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)
{
......
......@@ -69,7 +69,6 @@ ospf_neighbor_new(struct ospf_iface *ifa)
add_tail(&ifa->neigh_list, NODE n);
n->adj = 0;
n->csn = 0;
n->ldbdes = mb_allocz(pool, ifa->iface->mtu);
n->state = NEIGHBOR_DOWN;
init_lists(n);
......@@ -286,10 +285,10 @@ can_do_adj(struct ospf_neighbor *n)
{
case OSPF_IS_DOWN:
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;
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;
case OSPF_IS_DROTHER:
if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
......@@ -303,15 +302,15 @@ can_do_adj(struct ospf_neighbor *n)
i = 1;
break;
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;
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;
}
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;
}
......@@ -556,9 +555,8 @@ neighbor_timer_hook(timer * timer)
struct ospf_iface *ifa = n->ifa;
struct proto *p = &ifa->oa->po->proto;
OSPF_TRACE(D_EVENTS,
"Inactivity timer fired on interface %s for neighbor %I.",
ifa->iface->name, n->ip);
OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I.",
ifa->ifname, n->ip);
ospf_neigh_remove(n);
}
......@@ -591,7 +589,7 @@ ospf_neigh_bfd_hook(struct bfd_request *req)
if (req->down)
{
OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s",
n->ip, n->ifa->iface->name);
n->ip, n->ifa->ifname);
ospf_neigh_remove(n);
}
......@@ -641,8 +639,7 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
pos = "ptp ";
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
ospf_ns[n->state], pos, etime,
(ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name), n->ip);
ospf_ns[n->state], pos, etime, ifa->ifname, n->ip);
}
static void
......@@ -653,7 +650,7 @@ rxmt_timer_hook(timer * timer)
struct top_hash_entry *en;
DBG("%s: RXMT timer fired on interface %s for neigh: %I.\n",
p->name, n->ifa->iface->name, n->ip);
p->name, n->ifa->ifname, n->ip);
if(n->state < NEIGHBOR_EXSTART) return;
......
......@@ -232,7 +232,6 @@ ospf_start(struct proto *p)
struct ospf_area_config *ac;
po->router_id = proto_get_router_id(p->cf);
po->last_vlink_id = 0x80000000;
po->rfc1583 = c->rfc1583;
po->stub_router = c->stub_router;
po->ebit = 0;
......@@ -258,10 +257,13 @@ ospf_start(struct proto *p)
WALK_LIST(ac, c->area_list)
ospf_area_add(po, ac, 0);
if (c->abr)
ospf_open_vlink_sk(po);
/* Add all virtual links */
struct ospf_iface_patt *ic;
WALK_LIST(ic, c->vlink_list)
ospf_iface_new(po->backbone, NULL, ic);
ospf_iface_new_vlink(po, ic);
return PS_UP;
}
......@@ -277,7 +279,7 @@ ospf_dump(struct proto *p)
WALK_LIST(ifa, po->iface_list)
{
OSPF_TRACE(D_EVENTS, "Interface: %s", (ifa->iface ? ifa->iface->name : "(null)"));
OSPF_TRACE(D_EVENTS, "Interface: %s", ifa->ifname);
OSPF_TRACE(D_EVENTS, "state: %u", ifa->state);
OSPF_TRACE(D_EVENTS, "DR: %R", ifa->drid);
OSPF_TRACE(D_EVENTS, "BDR: %R", ifa->bdrid);
......@@ -381,7 +383,7 @@ schedule_net_lsa(struct ospf_iface *ifa)
{
struct proto *p = &ifa->oa->po->proto;
OSPF_TRACE(D_EVENTS, "Scheduling network-LSA origination for iface %s", ifa->iface->name);
OSPF_TRACE(D_EVENTS, "Scheduling network-LSA origination for iface %s", ifa->ifname);
ifa->orignet = 1;
}
......@@ -391,7 +393,7 @@ schedule_link_lsa(struct ospf_iface *ifa)
{
struct proto *p = &ifa->oa->po->proto;
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->iface->name);
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->ifname);
ifa->origlink = 1;
}
#endif
......@@ -631,7 +633,7 @@ ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
{
char *type = "<bug>";
switch(rte->attrs->source)
switch (rte->attrs->source)
{
case RTS_OSPF:
type = "I";
......@@ -769,7 +771,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
if (ifa)
ospf_iface_reconfigure(ifa, ip);
else
ospf_iface_new(po->backbone, NULL, ip);
ospf_iface_new_vlink(po, ip);
}
/* Delete remaining ifaces and areas */
......@@ -808,7 +810,7 @@ ospf_sh_neigh(struct proto *p, char *iff)
cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %-12s", "Router ID", "Pri",
" State", "DTime", "Interface", "Router IP");
WALK_LIST(ifa, po->iface_list)
if ((iff == NULL) || patmatch(iff, ifa->iface->name))
if ((iff == NULL) || patmatch(iff, ifa->ifname))
WALK_LIST(n, ifa->neigh_list)
ospf_sh_neigh_info(n);
cli_msg(0, "");
......@@ -917,7 +919,7 @@ ospf_sh_iface(struct proto *p, char *iff)
cli_msg(-1015, "%s:", p->name);
WALK_LIST(ifa, po->iface_list)
if ((iff == NULL) || patmatch(iff, ifa->iface->name))
if ((iff == NULL) || patmatch(iff, ifa->ifname))
ospf_iface_info(ifa);
cli_msg(0, "");
}
......
......@@ -10,14 +10,8 @@
#define _BIRD_OSPF_H_
#define MAXNETS 10
#define OSPF_MIN_PKT_SIZE 256
#define OSPF_MAX_PKT_SIZE 65535
/*
* RFC 2328 says, maximum packet size is 65535 (IP packet size
* limit). Really a bit less for OSPF, because this contains also IP
* header. This could be too much for small systems, so I normally
* allocate 2*mtu (i found one cisco sending packets mtu+16). OSPF
* packets are almost always sent small enough to not be fragmented.
*/
#ifdef LOCAL_DEBUG
#define OSPF_FORCE_DEBUG 1
......@@ -78,6 +72,8 @@ do { if ((p->debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
#define DEFAULT_ECMP_LIMIT 16
#define DEFAULT_TRANSINT 40
#define OSPF_VLINK_ID_OFFSET 0x80000000
struct ospf_config
{
......@@ -179,12 +175,14 @@ struct ospf_area_config
struct ospf_iface
{
node n;
struct iface *iface; /* Nest's iface, non-NULL (unless type OSPF_IT_VLINK) */
struct iface *iface; /* Nest's iface (NULL for vlinks) */
struct ifa *addr; /* IP prefix associated with that OSPF iface */
struct ospf_area *oa;
struct ospf_iface_patt *cf;
char *ifname; /* Interface name (iface->name), new one for vlinks */
pool *pool;
sock *sk; /* IP socket (for DD ...) */
sock *sk; /* IP socket */
list neigh_list; /* List of neigbours */
u32 cost; /* Cost of iface */
u32 waitint; /* number of sec before changing state from wait */
......@@ -273,6 +271,7 @@ struct ospf_iface
u8 sk_dr; /* Socket is a member of DRouters group */
u8 marked; /* Used in OSPF reconfigure */
u16 rxbuf; /* Buffer size */
u16 tx_length; /* Soft TX packet length limit, usually MTU */
u8 check_link; /* Whether iface link change is used */
u8 ecmp_weight; /* Weight used for ECMP */
u8 ptp_netmask; /* Send real netmask for P2P */
......@@ -704,13 +703,14 @@ struct ospf_neighbor
slist lsrtl; /* Link state retransmission list */
siterator lsrti;
struct top_graph *lsrth;
void *ldbdes; /* Last database description packet */
timer *rxmt_timer; /* RXMT timer */
list ackl[2];
#define ACKL_DIRECT 0
#define ACKL_DELAY 1
timer *ackd_timer; /* Delayed ack timer */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
void *ldd_buffer; /* Last database description packet */
u32 ldd_bsize; /* Buffer size for ldd_buffer */
u32 csn; /* Last received crypt seq number (for MD5) */
};
......@@ -783,6 +783,7 @@ struct proto_ospf
void *lsab; /* LSA buffer used when originating router LSAs */
int lsab_size, lsab_used;
linpool *nhpool; /* Linpool used for next hops computed in SPF */
sock *vlink_sk; /* IP socket used for vlink TX */
u32 router_id;
u32 last_vlink_id; /* Interface IDs for vlinks (starts at 0x80000000) */
};
......@@ -806,9 +807,9 @@ struct ospf_iface_patt
u32 vid;
int tx_tos;
int tx_priority;
u16 rxbuf;
#define OSPF_RXBUF_NORMAL 0
#define OSPF_RXBUF_LARGE 1
u16 tx_length;
u16 rx_buffer;
#define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
u16 autype; /* Not really used in OSPFv3 */
#define OSPF_AUTH_NONE 0
......@@ -822,6 +823,7 @@ struct ospf_iface_patt
u8 ptp_netmask; /* bool + 2 for unspecified */
u8 ttl_security; /* bool + 2 for TX only */
u8 bfd;
u8 bsd_secondary;
#ifdef OSPFv2
list *passwords;
......
......@@ -39,7 +39,6 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
unsigned
ospf_pkt_maxsize(struct ospf_iface *ifa)
{
unsigned mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu;
unsigned headers = SIZE_OF_IP_HEADER;
#ifdef OSPFv2
......@@ -47,7 +46,7 @@ ospf_pkt_maxsize(struct ospf_iface *ifa)