summaryrefslogtreecommitdiffstats
path: root/sys/netinet/ip_output.c
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2004-02-13 19:14:16 +0000
committermlaier <mlaier@FreeBSD.org>2004-02-13 19:14:16 +0000
commitda4d773b129fb1339d7b5fc23b93388b18952d3b (patch)
tree75fdee3c73dd1369e60e6348343749bdf159313a /sys/netinet/ip_output.c
parent09ad0862e6acad72dd0217846a1c16d5bea5c454 (diff)
downloadFreeBSD-src-da4d773b129fb1339d7b5fc23b93388b18952d3b.zip
FreeBSD-src-da4d773b129fb1339d7b5fc23b93388b18952d3b.tar.gz
This set of changes eliminates the use of MT_TAG "pseudo mbufs", replacing
them mostly with packet tags (one case is handled by using an mbuf flag since the linkage between "caller" and "callee" is direct and there's no need to incur the overhead of a packet tag). This is (mostly) work from: sam Silence from: -arch Approved by: bms(mentor), sam, rwatson
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r--sys/netinet/ip_output.c113
1 files changed, 60 insertions, 53 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index e567936..26d76cb 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -90,6 +90,7 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
#endif /*FAST_IPSEC*/
#include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
@@ -130,12 +131,11 @@ extern struct protosw inetsw[];
* inserted, so must have a NULL opt pointer.
*/
int
-ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
+ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
int flags, struct ip_moptions *imo, struct inpcb *inp)
{
struct ip *ip;
struct ifnet *ifp = NULL; /* keep compiler happy */
- struct mbuf *m;
int hlen = sizeof (struct ip);
int len, off, error = 0;
struct sockaddr_in *dst = NULL; /* keep compiler happy */
@@ -143,11 +143,13 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
int isbroadcast, sw_csum;
struct in_addr pkt_dst;
struct route iproute;
+ struct m_tag *dummytag; /* dummynet packet tag */
+ struct m_tag *mtag;
+ struct mbuf *m0; /* XXX */
#ifdef IPSEC
struct secpolicy *sp = NULL;
#endif
#ifdef FAST_IPSEC
- struct m_tag *mtag;
struct secpolicy *sp = NULL;
struct tdb_ident *tdbi;
int s;
@@ -157,42 +159,7 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
args.eh = NULL;
args.rule = NULL;
- args.next_hop = NULL;
- args.divert_rule = 0; /* divert cookie */
-
- /* Grab info from MT_TAG mbufs prepended to the chain. */
- for (; m0 && m0->m_type == MT_TAG; m0 = m0->m_next) {
- switch(m0->_m_tag_id) {
- default:
- printf("ip_output: unrecognised MT_TAG tag %d\n",
- m0->_m_tag_id);
- break;
-
- case PACKET_TAG_DUMMYNET:
- /*
- * the packet was already tagged, so part of the
- * processing was already done, and we need to go down.
- * Get parameters from the header.
- */
- args.rule = ((struct dn_pkt *)m0)->rule;
- opt = NULL ;
- ro = & ( ((struct dn_pkt *)m0)->ro ) ;
- imo = NULL ;
- dst = ((struct dn_pkt *)m0)->dn_dst ;
- ifp = ((struct dn_pkt *)m0)->ifp ;
- flags = ((struct dn_pkt *)m0)->flags ;
- break;
-
- case PACKET_TAG_DIVERT:
- args.divert_rule = (intptr_t)m0->m_data & 0xffff;
- break;
-
- case PACKET_TAG_IPFORWARD:
- args.next_hop = (struct sockaddr_in *)m0->m_data;
- break;
- }
- }
- m = m0;
+ args.next_hop = ip_claim_next_hop(m);
M_ASSERTPKTHDR(m);
@@ -204,7 +171,34 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro,
if (inp != NULL)
INP_LOCK_ASSERT(inp);
- if (args.rule != NULL) { /* dummynet already saw us */
+ /*
+ * When packet comes from dummynet restore state from
+ * previous processing instead of the header. Yech!
+ *
+ * XXX add conditional compilation?
+ */
+ dummytag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
+ if (dummytag != NULL) {
+ struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
+
+ /*
+ * NB: the route in the tag is known to have a
+ * reference that must be free'd, but doing this
+ * before the storage is reclaimed is painful due
+ * to some of the contorted code in this routine.
+ * So instead unlink the tag from the mbuf so it
+ * doesn't get reclaimed and do the cleanup explicitly
+ * below. We should be able to do this automatically
+ * using a uma dtor method when m_tag's can be
+ * allocated from zones.
+ */
+ m_tag_unlink(m, dummytag);
+
+ args.rule = dt->rule;
+ ro = &dt->ro;
+ dst = dt->dn_dst;
+ ifp = dt->ifp;
+
ip = mtod(m, struct ip *);
hlen = ip->ip_hl << 2 ;
if (ro->ro_rt)
@@ -557,7 +551,7 @@ sendit:
dst = (struct sockaddr_in *)state.dst;
if (error) {
/* mbuf is already reclaimed in ipsec4_output. */
- m0 = NULL;
+ m = NULL;
switch (error) {
case EHOSTUNREACH:
case ENETUNREACH:
@@ -795,11 +789,13 @@ spd_done:
}
#ifdef IPDIVERT
if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
- struct mbuf *clone = NULL;
+ struct mbuf *clone;
/* Clone packet if we're doing a 'tee' */
if ((off & IP_FW_PORT_TEE_FLAG) != 0)
- clone = m_dup(m, M_DONTWAIT);
+ clone = divert_clone(m);
+ else
+ clone = NULL;
/*
* XXX
@@ -816,7 +812,7 @@ spd_done:
ip->ip_off = htons(ip->ip_off);
/* Deliver packet to divert input routine */
- divert_packet(m, 0, off & 0xffff, args.divert_rule);
+ divert_packet(m, 0);
/* If 'tee', continue with original packet */
if (clone != NULL) {
@@ -894,26 +890,31 @@ spd_done:
break;
}
if (ia) { /* tell ip_input "dont filter" */
- struct m_hdr tag;
-
- tag.mh_type = MT_TAG;
- tag.mh_flags = PACKET_TAG_IPFORWARD;
- tag.mh_data = (caddr_t)args.next_hop;
- tag.mh_next = m;
- tag.mh_nextpkt = NULL;
+ mtag = m_tag_get(PACKET_TAG_IPFORWARD,
+ sizeof(struct sockaddr_in *),
+ M_NOWAIT);
+ if (mtag == NULL) {
+ /* XXX statistic */
+ error = ENOBUFS; /* XXX */
+ goto bad;
+ }
+ *(struct sockaddr_in **)(mtag+1) =
+ args.next_hop;
+ m_tag_prepend(m, mtag);
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = ifunit("lo0");
if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
m->m_pkthdr.csum_flags |=
CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m0->m_pkthdr.csum_data = 0xffff;
+ m->m_pkthdr.csum_data = 0xffff;
}
m->m_pkthdr.csum_flags |=
CSUM_IP_CHECKED | CSUM_IP_VALID;
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
- ip_input((struct mbuf *)&tag);
+ /* XXX netisr_queue(NETISR_IP, m); */
+ ip_input(m);
goto done;
}
/*
@@ -1070,6 +1071,12 @@ done:
RTFREE(ro->ro_rt);
ro->ro_rt = NULL;
}
+ if (dummytag) {
+ struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
+ if (dt->ro.ro_rt)
+ RTFREE(dt->ro.ro_rt);
+ m_tag_free(dummytag);
+ }
#ifdef IPSEC
if (sp != NULL) {
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
OpenPOWER on IntegriCloud