mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 10:46:22 +00:00
2004-09-24 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_write) ifdef fragmentation support. move actual fragmentation out to a new, similarly ifdefed, function. (ospf_write_frags) fragmented write support, moved from previous.
This commit is contained in:
parent
87d6f87aec
commit
0bfeca3f00
@ -507,6 +507,70 @@ ospf_swab_iph_toh (struct ip *iph)
|
|||||||
iph->ip_id = ntohs(iph->ip_id);
|
iph->ip_id = ntohs(iph->ip_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
||||||
|
void
|
||||||
|
ospf_write_frags (struct ospf_packet *op, struct ip *ip, struct msghdr *msg,
|
||||||
|
struct iovec *iov, int maxdatasize);
|
||||||
|
{
|
||||||
|
#define OSPF_WRITE_FRAG_SHIFT 3
|
||||||
|
|
||||||
|
assert ( op->length == stream_get_endp(op->s) );
|
||||||
|
|
||||||
|
/* we can but try.
|
||||||
|
*
|
||||||
|
* SunOS, BSD and BSD derived kernels likely will clear ip_id, as
|
||||||
|
* well as the IP_MF flag, making this all quite pointless.
|
||||||
|
*
|
||||||
|
* However, for a system on which IP_MF is left alone, and ip_id left
|
||||||
|
* alone or else which sets same ip_id for each fragment this might
|
||||||
|
* work, eg linux.
|
||||||
|
*
|
||||||
|
* XXX-TODO: It would be much nicer to have the kernel's use their
|
||||||
|
* existing fragmentation support to do this for us. Bugs/RFEs need to
|
||||||
|
* be raised against the various kernels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* set More Frag */
|
||||||
|
iph->ip_off |= IP_MF;
|
||||||
|
|
||||||
|
/* ip frag offset is expressed in units of 8byte words */
|
||||||
|
offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT;
|
||||||
|
|
||||||
|
while ( (stream_get_endp(op->s) - stream_get_getp (op->s))
|
||||||
|
> maxdatasize )
|
||||||
|
{
|
||||||
|
/* data length of this frag is to next offset value */
|
||||||
|
iov[1]->iov_len = offset << OSPF_WRITE_FRAG_SHIFT;
|
||||||
|
iph->ip_len = iov[1]->iov_len + sizeof (struct ip);
|
||||||
|
assert (iph->ip_len <= oi->ifp->mtu);
|
||||||
|
|
||||||
|
ospf_swab_iph_ton (iph);
|
||||||
|
|
||||||
|
ret = sendmsg (ospf->fd, msg, flags);
|
||||||
|
|
||||||
|
ospf_swab_iph_toh (iph);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
zlog_warn ("*** sendmsg in ospf_write to %s,"
|
||||||
|
" id %d, off %d, len %d failed with %s",
|
||||||
|
inet_ntoa (iph->ip_dst),
|
||||||
|
iph->ip_id,
|
||||||
|
iph->ip_off,
|
||||||
|
iph->ip_len,
|
||||||
|
strerror (errno));
|
||||||
|
|
||||||
|
iph->ip_off += offset;
|
||||||
|
stream_forward (op->s, iov[1]->iov_len);
|
||||||
|
iov[1]->iov_base = STREAM_PNT (op->s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup for final fragment */
|
||||||
|
iov[1]->iov_len = stream_get_endp(op->s) - stream_get_getp (op->s);
|
||||||
|
iph->ip_len = iov[1]->iov_len + sizeof (struct ip);
|
||||||
|
iph->ip_off &= (~IP_MF);
|
||||||
|
}
|
||||||
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
|
|
||||||
int
|
int
|
||||||
ospf_write (struct thread *thread)
|
ospf_write (struct thread *thread)
|
||||||
{
|
{
|
||||||
@ -521,10 +585,11 @@ ospf_write (struct thread *thread)
|
|||||||
int ret;
|
int ret;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
||||||
static u_int16_t ipid = 0;
|
static u_int16_t ipid = 0;
|
||||||
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
u_int16_t maxdatasize, offset;
|
u_int16_t maxdatasize, offset;
|
||||||
#define OSPF_WRITE_IPHL_SHIFT 2
|
#define OSPF_WRITE_IPHL_SHIFT 2
|
||||||
#define OSPF_WRITE_FRAG_SHIFT 3
|
|
||||||
|
|
||||||
ospf->t_write = NULL;
|
ospf->t_write = NULL;
|
||||||
|
|
||||||
@ -532,11 +597,13 @@ ospf_write (struct thread *thread)
|
|||||||
assert (node);
|
assert (node);
|
||||||
oi = getdata (node);
|
oi = getdata (node);
|
||||||
assert (oi);
|
assert (oi);
|
||||||
|
|
||||||
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
||||||
/* seed ipid static with low order bits of time */
|
/* seed ipid static with low order bits of time */
|
||||||
if (ipid == 0)
|
if (ipid == 0)
|
||||||
ipid = (time(NULL) & 0xffff);
|
ipid = (time(NULL) & 0xffff);
|
||||||
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
|
|
||||||
/* convenience - max OSPF data per packet */
|
/* convenience - max OSPF data per packet */
|
||||||
maxdatasize = oi->ifp->mtu - sizeof (struct ip);
|
maxdatasize = oi->ifp->mtu - sizeof (struct ip);
|
||||||
|
|
||||||
@ -578,14 +645,15 @@ ospf_write (struct thread *thread)
|
|||||||
iph.ip_v = IPVERSION;
|
iph.ip_v = IPVERSION;
|
||||||
iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
|
iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
|
||||||
iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
|
iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
|
||||||
iph.ip_id = 0;
|
|
||||||
|
|
||||||
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
||||||
/* XXX-MT: not thread-safe at all..
|
/* XXX-MT: not thread-safe at all..
|
||||||
* XXX: this presumes this is only programme sending OSPF packets
|
* XXX: this presumes this is only programme sending OSPF packets
|
||||||
* otherwise, no guarantee ipid will be unique
|
* otherwise, no guarantee ipid will be unique
|
||||||
*/
|
*/
|
||||||
iph.ip_id = ++ipid;
|
iph.ip_id = ++ipid;
|
||||||
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
|
|
||||||
iph.ip_off = 0;
|
iph.ip_off = 0;
|
||||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||||
iph.ip_ttl = OSPF_VL_IP_TTL;
|
iph.ip_ttl = OSPF_VL_IP_TTL;
|
||||||
@ -609,63 +677,10 @@ ospf_write (struct thread *thread)
|
|||||||
/* Sadly we can not rely on kernels to fragment packets because of either
|
/* Sadly we can not rely on kernels to fragment packets because of either
|
||||||
* IP_HDRINCL and/or multicast destination being set.
|
* IP_HDRINCL and/or multicast destination being set.
|
||||||
*/
|
*/
|
||||||
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
||||||
if ( op->length > maxdatasize )
|
if ( op->length > maxdatasize )
|
||||||
{
|
ospf_write_frags (&op, &ip, &msg, &iov, maxdatasize);
|
||||||
assert ( op->length == stream_get_endp(op->s) );
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
|
|
||||||
/* we can but try.
|
|
||||||
*
|
|
||||||
* SunOS, BSD and BSD derived kernels likely will clear ip_id, as
|
|
||||||
* well as the IP_MF flag, making this all quite pointless.
|
|
||||||
*
|
|
||||||
* However, for a system on which IP_MF is left alone, and ip_id left
|
|
||||||
* alone or else which sets same ip_id for each fragment this might
|
|
||||||
* work, eg linux.
|
|
||||||
*
|
|
||||||
* XXX-TODO: It would be much nicer to have the kernel's use their
|
|
||||||
* existing fragmentation support to do this for us. Bugs/RFEs need to
|
|
||||||
* be raised against the various kernels.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* set More Frag */
|
|
||||||
iph.ip_off |= IP_MF;
|
|
||||||
|
|
||||||
/* ip frag offset is expressed in units of 8byte words */
|
|
||||||
offset = maxdatasize >> OSPF_WRITE_FRAG_SHIFT;
|
|
||||||
|
|
||||||
while ( (stream_get_endp(op->s) - stream_get_getp (op->s))
|
|
||||||
> maxdatasize )
|
|
||||||
{
|
|
||||||
/* data length of this frag is to next offset value */
|
|
||||||
iov[1].iov_len = offset << OSPF_WRITE_FRAG_SHIFT;
|
|
||||||
iph.ip_len = iov[1].iov_len + sizeof (struct ip);
|
|
||||||
assert (iph.ip_len <= oi->ifp->mtu);
|
|
||||||
|
|
||||||
ospf_swab_iph_ton (&iph);
|
|
||||||
|
|
||||||
ret = sendmsg (ospf->fd, &msg, flags);
|
|
||||||
|
|
||||||
ospf_swab_iph_toh (&iph);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
zlog_warn ("*** sendmsg in ospf_write to %s,"
|
|
||||||
" id %d, off %d, len %d failed with %s",
|
|
||||||
inet_ntoa (iph.ip_dst),
|
|
||||||
iph.ip_id,
|
|
||||||
iph.ip_off,
|
|
||||||
iph.ip_len,
|
|
||||||
strerror (errno));
|
|
||||||
|
|
||||||
iph.ip_off += offset;
|
|
||||||
stream_forward (op->s, iov[1].iov_len);
|
|
||||||
iov[1].iov_base = STREAM_PNT (op->s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup for final fragment */
|
|
||||||
iov[1].iov_len = stream_get_endp(op->s) - stream_get_getp (op->s);
|
|
||||||
iph.ip_len = iov[1].iov_len + sizeof (struct ip);
|
|
||||||
iph.ip_off &= (~IP_MF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* send final fragment (could be first) */
|
/* send final fragment (could be first) */
|
||||||
ospf_swab_iph_ton (&iph);
|
ospf_swab_iph_ton (&iph);
|
||||||
|
Loading…
Reference in New Issue
Block a user