summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_output.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2023-05-07 16:23:25 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2023-05-07 16:23:25 +0000
commit825eaba69832501b514af1cc8ad99254a7f57b75 (patch)
treea019d4a5e81f296df2c3b33f58a93c08ce977a07 /sys/netinet/ip_output.c
parent940296c59874928d526c5668f93b30d0f3d60dd5 (diff)
I preparation for TSO in software, cleanup the fragment code. Use
if_output_ml() to send mbuf lists to interfaces. This can be used for TSO, fragments, ARP and ND6. Rename variable fml to ml. In pf_route6() split the if else block. Put the safety check (hlen + firstlen < tlen) into ip_fragment(). It makes the code correct in case the packet is too short to be fragmented. This should not happen, but other functions also have this logic. No functional change. OK sashan@
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r--sys/netinet/ip_output.c51
1 files changed, 21 insertions, 30 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index b0c6ed720f6..c44ad8a136d 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.382 2022/08/12 17:04:16 bluhm Exp $ */
+/* $OpenBSD: ip_output.c,v 1.383 2023/05/07 16:23:23 bluhm Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -104,7 +104,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
{
struct ip *ip;
struct ifnet *ifp = NULL;
- struct mbuf_list fml;
+ struct mbuf_list ml;
int hlen = sizeof (struct ip);
int error = 0;
struct route iproute;
@@ -505,19 +505,10 @@ sendit:
goto bad;
}
- error = ip_fragment(m, &fml, ifp, mtu);
- if (error)
+ if ((error = ip_fragment(m, &ml, ifp, mtu)) ||
+ (error = if_output_ml(ifp, &ml, sintosa(dst), ro->ro_rt)))
goto done;
-
- while ((m = ml_dequeue(&fml)) != NULL) {
- error = ifp->if_output(ifp, m, sintosa(dst), ro->ro_rt);
- if (error)
- break;
- }
- if (error)
- ml_purge(&fml);
- else
- ipstat_inc(ips_fragmented);
+ ipstat_inc(ips_fragmented);
done:
if (ro == &iproute && ro->ro_rt)
@@ -677,16 +668,15 @@ ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route *ro, int fwd)
#endif /* IPSEC */
int
-ip_fragment(struct mbuf *m0, struct mbuf_list *fml, struct ifnet *ifp,
+ip_fragment(struct mbuf *m0, struct mbuf_list *ml, struct ifnet *ifp,
u_long mtu)
{
- struct mbuf *m;
struct ip *ip;
int firstlen, hlen, tlen, len, off;
int error;
- ml_init(fml);
- ml_enqueue(fml, m0);
+ ml_init(ml);
+ ml_enqueue(ml, m0);
ip = mtod(m0, struct ip *);
hlen = ip->ip_hl << 2;
@@ -705,10 +695,11 @@ ip_fragment(struct mbuf *m0, struct mbuf_list *fml, struct ifnet *ifp,
in_proto_cksum_out(m0, NULL);
/*
- * Loop through length of segment after first fragment,
+ * Loop through length of payload after first fragment,
* make new header and copy data of each part and link onto chain.
*/
for (off = hlen + firstlen; off < tlen; off += len) {
+ struct mbuf *m;
struct ip *mhip;
int mhlen;
@@ -717,8 +708,7 @@ ip_fragment(struct mbuf *m0, struct mbuf_list *fml, struct ifnet *ifp,
error = ENOBUFS;
goto bad;
}
- ml_enqueue(fml, m);
-
+ ml_enqueue(ml, m);
if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0)
goto bad;
m->m_data += max_linkhdr;
@@ -762,25 +752,26 @@ ip_fragment(struct mbuf *m0, struct mbuf_list *fml, struct ifnet *ifp,
* Update first fragment by trimming what's been copied out
* and updating header, then send each fragment (in order).
*/
- m = m0;
- m_adj(m, hlen + firstlen - tlen);
- ip->ip_off |= htons(IP_MF);
- ip->ip_len = htons(m->m_pkthdr.len);
+ if (hlen + firstlen < tlen) {
+ m_adj(m0, hlen + firstlen - tlen);
+ ip->ip_off |= htons(IP_MF);
+ }
+ ip->ip_len = htons(m0->m_pkthdr.len);
ip->ip_sum = 0;
- if (in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4))
- m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
+ if (in_ifcap_cksum(m0, ifp, IFCAP_CSUM_IPv4))
+ m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
else {
ipstat_inc(ips_outswcsum);
- ip->ip_sum = in_cksum(m, hlen);
+ ip->ip_sum = in_cksum(m0, hlen);
}
- ipstat_add(ips_ofragments, ml_len(fml));
+ ipstat_add(ips_ofragments, ml_len(ml));
return (0);
bad:
ipstat_inc(ips_odropped);
- ml_purge(fml);
+ ml_purge(ml);
return (error);
}