summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_mbuf2.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2002-12-30 20:22:40 +0000
committersam <sam@FreeBSD.org>2002-12-30 20:22:40 +0000
commitb16cb0a948acd6a3b5f47aa494607a001944c194 (patch)
tree984c2041a8941be016b4cab972816b51adcc818d /sys/kern/uipc_mbuf2.c
parent83fcaa45a1be401bd2ecafa45dbfb492a71532b7 (diff)
downloadFreeBSD-src-b16cb0a948acd6a3b5f47aa494607a001944c194.zip
FreeBSD-src-b16cb0a948acd6a3b5f47aa494607a001944c194.tar.gz
Correct mbuf packet header propagation. Previously, packet headers
were sometimes propagated using M_COPY_PKTHDR which actually did something between a "move" and a "copy" operation. This is replaced by M_MOVE_PKTHDR (which copies the pkthdr contents and "removes" it from the source mbuf) and m_dup_pkthdr which copies the packet header contents including any m_tag chain. This corrects numerous problems whereby mbuf tags could be lost during packet manipulations. These changes also introduce arguments to m_tag_copy and m_tag_copy_chain to specify if the tag copy work should potentially block. This introduces an incompatibility with openbsd which we may want to revisit. Note that move/dup of packet headers does not handle target mbufs that have a cluster bound to them. We may want to support this; for now we watch for it with an assert. Finally, M_COPYFLAGS was updated to include M_FIRSTFRAG|M_LASTFRAG. Supported by: Vernier Networks Reviewed by: Robert Watson <rwatson@FreeBSD.org>
Diffstat (limited to 'sys/kern/uipc_mbuf2.c')
-rw-r--r--sys/kern/uipc_mbuf2.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/sys/kern/uipc_mbuf2.c b/sys/kern/uipc_mbuf2.c
index 63d86b7..9dbb7a3 100644
--- a/sys/kern/uipc_mbuf2.c
+++ b/sys/kern/uipc_mbuf2.c
@@ -298,8 +298,10 @@ m_dup1(struct mbuf *m, int off, int len, int wait)
if (!n)
return NULL;
- if (copyhdr)
- M_COPY_PKTHDR(n, m);
+ if (copyhdr && !m_dup_pkthdr(n, m, wait)) {
+ m_free(n);
+ return NULL;
+ }
m_copydata(m, off, len, mtod(n, caddr_t));
return n;
}
@@ -392,12 +394,12 @@ m_tag_locate(struct mbuf *m, u_int32_t cookie, int type, struct m_tag *t)
/* Copy a single tag. */
struct m_tag *
-m_tag_copy(struct m_tag *t)
+m_tag_copy(struct m_tag *t, int how)
{
struct m_tag *p;
KASSERT(t, ("m_tag_copy: null tag"));
- p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, M_NOWAIT);
+ p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, how);
if (p == NULL)
return (NULL);
bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */
@@ -411,7 +413,7 @@ m_tag_copy(struct m_tag *t)
* destination mbuf.
*/
int
-m_tag_copy_chain(struct mbuf *to, struct mbuf *from)
+m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how)
{
struct m_tag *p, *t, *tprev = NULL;
@@ -419,7 +421,7 @@ m_tag_copy_chain(struct mbuf *to, struct mbuf *from)
("m_tag_copy_chain: null argument, to %p from %p", to, from));
m_tag_delete_chain(to, NULL);
SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) {
- t = m_tag_copy(p);
+ t = m_tag_copy(p, how);
if (t == NULL) {
m_tag_delete_chain(to, NULL);
return 0;
OpenPOWER on IntegriCloud