aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2019-05-24 22:30:40 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2019-05-24 22:30:40 +0000
commitfb3bc59600e25268ed5750fdc351b1e9423a8fb4 (patch)
treea42bc7a343914230357efb531136163780fedcd9 /sys/netinet
parent07e007e1ca0e72bea91f68ae639fd5266cf7c388 (diff)
Notes
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in_pcb.c33
-rw-r--r--sys/netinet/ip_output.c81
2 files changed, 59 insertions, 55 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index af91d18ae2a8d..17fa348955958 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -3274,13 +3274,6 @@ in_pcbattach_txrtlmt(struct inpcb *inp, struct ifnet *ifp,
error = EOPNOTSUPP;
} else {
error = ifp->if_snd_tag_alloc(ifp, &params, &inp->inp_snd_tag);
-
- /*
- * At success increment the refcount on
- * the send tag's network interface:
- */
- if (error == 0)
- if_ref(inp->inp_snd_tag->ifp);
}
return (error);
}
@@ -3293,7 +3286,6 @@ void
in_pcbdetach_txrtlmt(struct inpcb *inp)
{
struct m_snd_tag *mst;
- struct ifnet *ifp;
INP_WLOCK_ASSERT(inp);
@@ -3303,19 +3295,7 @@ in_pcbdetach_txrtlmt(struct inpcb *inp)
if (mst == NULL)
return;
- ifp = mst->ifp;
- if (ifp == NULL)
- return;
-
- /*
- * If the device was detached while we still had reference(s)
- * on the ifp, we assume if_snd_tag_free() was replaced with
- * stubs.
- */
- ifp->if_snd_tag_free(mst);
-
- /* release reference count on network interface */
- if_rele(ifp);
+ m_snd_tag_rele(mst);
}
/*
@@ -3361,6 +3341,17 @@ in_pcboutput_txrtlmt(struct inpcb *inp, struct ifnet *ifp, struct mbuf *mb)
max_pacing_rate = socket->so_max_pacing_rate;
/*
+ * If the existing send tag is for the wrong interface due to
+ * a route change, first drop the existing tag. Set the
+ * CHANGED flag so that we will keep trying to allocate a new
+ * tag if we fail to allocate one this time.
+ */
+ if (inp->inp_snd_tag != NULL && inp->inp_snd_tag->ifp != ifp) {
+ in_pcbdetach_txrtlmt(inp);
+ inp->inp_flags2 |= INP_RATE_LIMIT_CHANGED;
+ }
+
+ /*
* NOTE: When attaching to a network interface a reference is
* made to ensure the network interface doesn't go away until
* all ratelimit connections are gone. The network interface
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 82b208439cfb5..b48350fd5c7a8 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -204,6 +204,51 @@ ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp,
return 0;
}
+static int
+ip_output_send(struct inpcb *inp, struct ifnet *ifp, struct mbuf *m,
+ const struct sockaddr_in *gw, struct route *ro)
+{
+ struct m_snd_tag *mst;
+ int error;
+
+ MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0);
+ mst = NULL;
+
+#ifdef RATELIMIT
+ if (inp != NULL) {
+ if ((inp->inp_flags2 & INP_RATE_LIMIT_CHANGED) != 0 ||
+ (inp->inp_snd_tag != NULL &&
+ inp->inp_snd_tag->ifp != ifp))
+ in_pcboutput_txrtlmt(inp, ifp, m);
+
+ if (inp->inp_snd_tag != NULL)
+ mst = inp->inp_snd_tag;
+ }
+#endif
+ if (mst != NULL) {
+ KASSERT(m->m_pkthdr.rcvif == NULL,
+ ("trying to add a send tag to a forwarded packet"));
+ if (mst->ifp != ifp) {
+ error = EAGAIN;
+ goto done;
+ }
+
+ /* stamp send tag on mbuf */
+ m->m_pkthdr.snd_tag = m_snd_tag_ref(mst);
+ m->m_pkthdr.csum_flags |= CSUM_SND_TAG;
+ }
+
+ error = (*ifp->if_output)(ifp, m, (const struct sockaddr *)gw, ro);
+
+done:
+ /* Check for route change invalidating send tags. */
+#ifdef RATELIMIT
+ if (error == EAGAIN)
+ in_pcboutput_eagain(inp);
+#endif
+ return (error);
+}
+
/*
* IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
@@ -687,23 +732,7 @@ sendit:
*/
m_clrprotoflags(m);
IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL);
-#ifdef RATELIMIT
- if (inp != NULL) {
- if (inp->inp_flags2 & INP_RATE_LIMIT_CHANGED)
- in_pcboutput_txrtlmt(inp, ifp, m);
- /* stamp send tag on mbuf */
- m->m_pkthdr.snd_tag = inp->inp_snd_tag;
- } else {
- m->m_pkthdr.snd_tag = NULL;
- }
-#endif
- error = (*ifp->if_output)(ifp, m,
- (const struct sockaddr *)gw, ro);
-#ifdef RATELIMIT
- /* check for route change */
- if (error == EAGAIN)
- in_pcboutput_eagain(inp);
-#endif
+ error = ip_output_send(inp, ifp, m, gw, ro);
goto done;
}
@@ -739,23 +768,7 @@ sendit:
IP_PROBE(send, NULL, NULL, mtod(m, struct ip *), ifp,
mtod(m, struct ip *), NULL);
-#ifdef RATELIMIT
- if (inp != NULL) {
- if (inp->inp_flags2 & INP_RATE_LIMIT_CHANGED)
- in_pcboutput_txrtlmt(inp, ifp, m);
- /* stamp send tag on mbuf */
- m->m_pkthdr.snd_tag = inp->inp_snd_tag;
- } else {
- m->m_pkthdr.snd_tag = NULL;
- }
-#endif
- error = (*ifp->if_output)(ifp, m,
- (const struct sockaddr *)gw, ro);
-#ifdef RATELIMIT
- /* check for route change */
- if (error == EAGAIN)
- in_pcboutput_eagain(inp);
-#endif
+ error = ip_output_send(inp, ifp, m, gw, ro);
} else
m_freem(m);
}