PERFORCE change 43019 for review
Sam Leffler
sam at FreeBSD.org
Mon Nov 24 16:38:04 PST 2003
http://perforce.freebsd.org/chv.cgi?CH=43019
Change 43019 by sam at sam_ebb on 2003/11/24 16:37:31
replace MT_TAG mbufs by m_tag's for divert sockets; move
divert-related definitions to a new ip_divert.h file
Affected files ...
.. //depot/projects/netperf/sys/net/if_ethersubr.c#13 edit
.. //depot/projects/netperf/sys/netinet/in_proto.c#7 edit
.. //depot/projects/netperf/sys/netinet/ip_divert.c#18 edit
.. //depot/projects/netperf/sys/netinet/ip_divert.h#1 add
.. //depot/projects/netperf/sys/netinet/ip_fastfwd.c#4 edit
.. //depot/projects/netperf/sys/netinet/ip_fw.h#5 edit
.. //depot/projects/netperf/sys/netinet/ip_fw2.c#19 edit
.. //depot/projects/netperf/sys/netinet/ip_input.c#26 edit
.. //depot/projects/netperf/sys/netinet/ip_output.c#19 edit
.. //depot/projects/netperf/sys/netinet/ip_var.h#14 edit
Differences ...
==== //depot/projects/netperf/sys/net/if_ethersubr.c#13 (text+ko) ====
@@ -393,7 +393,6 @@
args.m = m; /* the packet we are looking at */
args.oif = dst; /* destination, if any */
- args.divert_rule = 0; /* we do not support divert yet */
args.rule = *rule; /* matching rule to restart */
args.next_hop = NULL; /* we do not support forward yet */
args.eh = &save_eh; /* MAC header for bridged/MAC packets */
==== //depot/projects/netperf/sys/netinet/in_proto.c#7 (text+ko) ====
@@ -57,6 +57,7 @@
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
+#include <netinet/ip_divert.h>
#include <netinet/igmp_var.h>
#ifdef PIM
#include <netinet/pim_var.h>
==== //depot/projects/netperf/sys/netinet/ip_divert.c#18 (text+ko) ====
@@ -68,6 +68,7 @@
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
+#include <netinet/ip_divert.h>
#include <netinet/ip_var.h>
/*
@@ -150,17 +151,21 @@
* then pass them along with mbuf chain.
*/
void
-divert_packet(struct mbuf *m, int incoming, int port, int rule)
+divert_packet(struct mbuf *m, int incoming)
{
struct ip *ip;
struct inpcb *inp;
struct socket *sa;
u_int16_t nport;
struct sockaddr_in divsrc;
+ struct m_tag *mtag;
- /* Sanity check */
- KASSERT(port != 0, ("%s: port=0", __func__));
-
+ mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
+ if (mtag == NULL) {
+ printf("%s: no divert tag\n", __func__);
+ m_freem(m);
+ return;
+ }
/* Assure header */
if (m->m_len < sizeof(struct ip) &&
(m = m_pullup(m, sizeof(struct ip))) == 0)
@@ -174,7 +179,7 @@
bzero(&divsrc, sizeof(divsrc));
divsrc.sin_len = sizeof(divsrc);
divsrc.sin_family = AF_INET;
- divsrc.sin_port = rule; /* record matching rule */
+ divsrc.sin_port = divert_cookie(mtag); /* record matching rule */
if (incoming) {
struct ifaddr *ifa;
@@ -234,7 +239,7 @@
mtx_lock(&Giant);
/* Put packet on socket queue, if any */
sa = NULL;
- nport = htons((u_int16_t)port);
+ nport = htons((u_int16_t)divert_info(mtag));
INP_INFO_RLOCK(&divcbinfo);
LIST_FOREACH(inp, &divcb, inp_list) {
INP_LOCK(inp);
@@ -273,19 +278,8 @@
struct sockaddr_in *sin, struct mbuf *control)
{
int error = 0;
- struct m_hdr divert_tag;
- /*
- * Prepare the tag for divert info. Note that a packet
- * with a 0 tag in mh_data is effectively untagged,
- * so we could optimize that case.
- */
- divert_tag.mh_type = MT_TAG;
- divert_tag.mh_flags = PACKET_TAG_DIVERT;
- divert_tag.mh_next = m;
- divert_tag.mh_data = 0; /* the matching rule # */
- divert_tag.mh_nextpkt = NULL;
- m->m_pkthdr.rcvif = NULL; /* XXX is it necessary ? */
+ KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null"));
#ifdef MAC
mac_create_mbuf_from_socket(so, m);
@@ -296,9 +290,21 @@
/* Loopback avoidance and state recovery */
if (sin) {
+ struct m_tag *mtag;
+ struct divert_tag *dt;
int i;
- divert_tag.mh_data = (caddr_t)(uintptr_t)sin->sin_port;
+ mtag = m_tag_get(PACKET_TAG_DIVERT,
+ sizeof(struct divert_tag), M_NOWAIT);
+ if (mtag == NULL) {
+ error = ENOBUFS;
+ goto cantsend;
+ }
+ dt = (struct divert_tag *)(mtag+1);
+ dt->info = 0;
+ dt->cookie = sin->sin_port;
+ m_tag_prepend(m, mtag);
+
/*
* Find receive interface with the given name, stuffed
* (if it exists) in the sin_zero[] field.
@@ -335,7 +341,7 @@
/* Send packet to output processing */
ipstat.ips_rawout++; /* XXX */
- error = ip_output((struct mbuf *)&divert_tag,
+ error = ip_output(m,
inp->inp_options, NULL,
(so->so_options & SO_DONTROUTE) |
IP_ALLOWBROADCAST | IP_RAWOUTPUT,
@@ -362,7 +368,7 @@
m->m_pkthdr.rcvif = ifa->ifa_ifp;
}
/* Send packet to input processing */
- ip_input((struct mbuf *)&divert_tag);
+ ip_input(m);
}
return error;
@@ -372,6 +378,27 @@
return error;
}
+/*
+ * Return a copy of the specified packet, but without
+ * the divert tag. This is used when packets are ``tee'd''
+ * and we want the cloned copy to not have divert processing.
+ */
+struct mbuf *
+divert_clone(struct mbuf *m)
+{
+ struct mbuf *clone;
+ struct m_tag *mtag;
+
+ clone = m_dup(m, M_DONTWAIT);
+ if (clone != NULL) {
+ /* strip divert tag from copy */
+ mtag = m_tag_find(clone, PACKET_TAG_DIVERT, NULL);
+ if (mtag != NULL)
+ m_tag_delete(clone, mtag);
+ }
+ return clone;
+}
+
static int
div_attach(struct socket *so, int proto, struct thread *td)
{
==== //depot/projects/netperf/sys/netinet/ip_fastfwd.c#4 (text+ko) ====
@@ -110,6 +110,7 @@
#include <machine/in_cksum.h>
#include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
static int ipfastforward_active = 0;
@@ -373,25 +374,13 @@
/*
* See if this is a fragment
*/
- if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
- MGETHDR(tag, M_DONTWAIT, MT_TAG);
- if (tag == NULL)
- goto drop;
- tag->m_flags = PACKET_TAG_DIVERT;
- tag->m_data = (caddr_t)(intptr_t)args.divert_rule;
- tag->m_next = m;
- /* XXX: really bloody hack, see ip_input */
- tag->m_nextpkt = (struct mbuf *)1;
- m = tag;
- tag = NULL;
-
+ if (ip->ip_off & (IP_MF | IP_OFFMASK))
goto droptoours;
- }
/*
* Tee packet
*/
if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
- teem = m_dup(m, M_DONTWAIT);
+ teem = divert_clone(m);
else
teem = m;
if (teem == NULL)
@@ -413,7 +402,7 @@
/*
* Deliver packet to divert input routine
*/
- divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule);
+ divert_packet(teem, 0);
/*
* If this was not tee, we are done
*/
@@ -560,27 +549,13 @@
/*
* See if this is a fragment
*/
- if (ip->ip_off & (IP_MF | IP_OFFMASK)) {
- MGETHDR(tag, M_DONTWAIT, MT_TAG);
- if (tag == NULL) {
- RTFREE(ro.ro_rt);
- goto drop;
- }
- tag->m_flags = PACKET_TAG_DIVERT;
- tag->m_data = (caddr_t)(intptr_t)args.divert_rule;
- tag->m_next = m;
- /* XXX: really bloody hack, see ip_input */
- tag->m_nextpkt = (struct mbuf *)1;
- m = tag;
- tag = NULL;
-
+ if (ip->ip_off & (IP_MF | IP_OFFMASK))
goto droptoours;
- }
/*
* Tee packet
*/
if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
- teem = m_dup(m, M_DONTWAIT);
+ teem = divert_clone(m);
else
teem = m;
if (teem == NULL)
@@ -602,7 +577,7 @@
/*
* Deliver packet to divert input routine
*/
- divert_packet(teem, 0, ipfw & 0xffff, args.divert_rule);
+ divert_packet(teem, 0);
/*
* If this was not tee, we are done
*/
==== //depot/projects/netperf/sys/netinet/ip_fw.h#5 (text+ko) ====
@@ -400,7 +400,6 @@
int flags; /* for dummynet */
struct ipfw_flow_id f_id; /* grabbed from IP header */
- u_int16_t divert_rule; /* divert cookie */
u_int32_t retval;
};
==== //depot/projects/netperf/sys/netinet/ip_fw2.c#19 (text+ko) ====
@@ -65,6 +65,7 @@
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
@@ -1462,6 +1463,7 @@
int dyn_dir = MATCH_UNKNOWN;
ipfw_dyn_rule *q = NULL;
struct ip_fw_chain *chain = &layer3_chain;
+ struct m_tag *mtag;
if (m->m_flags & M_SKIP_FIREWALL)
return 0; /* accept */
@@ -1550,6 +1552,7 @@
after_ip_checks:
IPFW_LOCK(chain); /* XXX expensive? can we run lock free? */
+ mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
if (args->rule) {
/*
* Packet has already been tagged. Look for the next rule
@@ -1572,7 +1575,7 @@
* Find the starting rule. It can be either the first
* one, or the one after divert_rule if asked so.
*/
- int skipto = args->divert_rule;
+ int skipto = mtag ? divert_cookie(mtag) : 0;
f = chain->rules;
if (args->eh == NULL && skipto != 0) {
@@ -1588,7 +1591,9 @@
}
}
}
- args->divert_rule = 0; /* reset to avoid confusion later */
+ /* reset divert rule to avoid confusion later */
+ if (mtag)
+ m_tag_delete(m, mtag);
/*
* Now scan the rules, and parse microinstructions for each rule.
@@ -2023,14 +2028,29 @@
goto done;
case O_DIVERT:
- case O_TEE:
+ case O_TEE: {
+ struct divert_tag *dt;
+
if (args->eh) /* not on layer 2 */
break;
- args->divert_rule = f->rulenum;
- retval = (cmd->opcode == O_DIVERT) ?
+ mtag = m_tag_get(PACKET_TAG_DIVERT,
+ sizeof(struct divert_tag),
+ M_NOWAIT);
+ if (mtag == NULL) {
+ /* XXX statistic */
+ /* drop packet */
+ IPFW_UNLOCK(chain);
+ return IP_FW_PORT_DENY_FLAG;
+ }
+ dt = (struct divert_tag *)(mtag+1);
+ dt->cookie = f->rulenum;
+ dt->info = (cmd->opcode == O_DIVERT) ?
cmd->arg1 :
cmd->arg1 | IP_FW_PORT_TEE_FLAG;
+ m_tag_prepend(m, mtag);
+ retval = dt->info;
goto done;
+ }
case O_COUNT:
case O_SKIPTO:
==== //depot/projects/netperf/sys/netinet/ip_input.c#26 (text+ko) ====
@@ -78,6 +78,7 @@
#include <sys/socketvar.h>
#include <netinet/ip_fw.h>
+#include <netinet/ip_divert.h>
#include <netinet/ip_dummynet.h>
#ifdef IPSEC
@@ -239,8 +240,7 @@
static void ip_forward(struct mbuf *m, int srcrt,
struct sockaddr_in *next_hop);
static void ip_freef(struct ipqhead *, struct ipq *);
-static struct mbuf *ip_reass(struct mbuf *, struct ipqhead *,
- struct ipq *, u_int32_t *, u_int16_t *);
+static struct mbuf *ip_reass(struct mbuf *, struct ipqhead *, struct ipq *);
/*
* IP initialization: fill in IP protocol switch table.
@@ -303,7 +303,9 @@
int ours = 0;
u_short sum;
struct in_addr pkt_dst;
- u_int32_t divert_info = 0; /* packet divert/tee info */
+#ifdef IPDIVERT
+ u_int32_t divert_info; /* packet divert/tee info */
+#endif
struct ip_fw_args args;
int dchg = 0; /* dest changed after fw */
#ifdef PFIL_HOOKS
@@ -318,7 +320,6 @@
args.eh = NULL;
args.oif = NULL;
- args.divert_rule = 0; /* divert cookie */
args.next_hop = NULL;
/*
@@ -339,10 +340,6 @@
m->_m_tag_id);
break;
- case PACKET_TAG_DIVERT:
- args.divert_rule = (intptr_t)m->m_hdr.mh_data & 0xffff;
- break;
-
case PACKET_TAG_IPFORWARD:
args.next_hop = (struct sockaddr_in *)m->m_hdr.mh_data;
break;
@@ -527,7 +524,6 @@
#ifdef IPDIVERT
if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
/* Divert or tee packet */
- divert_info = i;
goto ours;
}
#endif
@@ -835,13 +831,11 @@
/*
* Attempt reassembly; if it succeeds, proceed.
- * ip_reass() will return a different mbuf, and update
- * the divert info in divert_info and args.divert_rule.
+ * ip_reass() will return a different mbuf.
*/
ipstat.ips_fragments++;
m->m_pkthdr.header = ip;
- m = ip_reass(m,
- &ipq[sum], fp, &divert_info, &args.divert_rule);
+ m = ip_reass(m, &ipq[sum], fp);
IPQ_UNLOCK();
if (m == 0)
return;
@@ -851,7 +845,7 @@
hlen = ip->ip_hl << 2;
#ifdef IPDIVERT
/* Restore original checksum before diverting packet */
- if (divert_info != 0) {
+ if (divert_find_info(m) != 0) {
ip->ip_len += hlen;
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
@@ -872,12 +866,15 @@
/*
* Divert or tee packet to the divert protocol if required.
*/
+ divert_info = divert_find_info(m);
if (divert_info != 0) {
- struct mbuf *clone = NULL;
+ struct mbuf *clone;
/* Clone packet if we're doing a 'tee' */
if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0)
- clone = m_dup(m, M_DONTWAIT);
+ clone = divert_clone(m);
+ else
+ clone = NULL;
/* Restore packet header fields to original values */
ip->ip_len += hlen;
@@ -885,7 +882,7 @@
ip->ip_off = htons(ip->ip_off);
/* Deliver packet to divert input routine */
- divert_packet(m, 1, divert_info & 0xffff, args.divert_rule);
+ divert_packet(m, 1);
ipstat.ips_delivered++;
/* If 'tee', continue with original packet */
@@ -896,12 +893,11 @@
ip->ip_len += hlen;
/*
* Jump backwards to complete processing of the
- * packet. But first clear divert_info to avoid
- * entering this block again.
- * We do not need to clear args.divert_rule
- * or args.next_hop as they will not be used.
+ * packet. We do not need to clear args.next_hop
+ * as that will not be used again and the cloned packet
+ * doesn't contain a divert packet tag so we won't
+ * re-entry this block.
*/
- divert_info = 0;
goto pass;
}
#endif
@@ -995,8 +991,7 @@
*/
static struct mbuf *
-ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp,
- u_int32_t *divinfo, u_int16_t *divert_rule)
+ip_reass(struct mbuf *m, struct ipqhead *head, struct ipq *fp)
{
struct ip *ip = mtod(m, struct ip *);
register struct mbuf *p, *q, *nq;
@@ -1038,10 +1033,6 @@
fp->ipq_dst = ip->ip_dst;
fp->ipq_frags = m;
m->m_nextpkt = NULL;
-#ifdef IPDIVERT
- fp->ipq_div_info = 0;
- fp->ipq_div_cookie = 0;
-#endif
goto inserted;
} else {
fp->ipq_nfrags++;
@@ -1125,16 +1116,15 @@
inserted:
#ifdef IPDIVERT
- /*
- * Transfer firewall instructions to the fragment structure.
- * Only trust info in the fragment at offset 0.
- */
- if (ip->ip_off == 0) {
- fp->ipq_div_info = *divinfo;
- fp->ipq_div_cookie = *divert_rule;
+ if (ip->ip_off != 0) {
+ /*
+ * Strip any divert information; only the info
+ * on the first fragment is used/kept.
+ */
+ struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
+ if (mtag)
+ m_tag_delete(m, mtag);
}
- *divinfo = 0;
- *divert_rule = 0;
#endif
/*
@@ -1200,15 +1190,7 @@
mac_destroy_ipq(fp);
#endif
-#ifdef IPDIVERT
/*
- * Extract firewall instructions from the fragment structure.
- */
- *divinfo = fp->ipq_div_info;
- *divert_rule = fp->ipq_div_cookie;
-#endif
-
- /*
* Create header for new ip packet by
* modifying header of first packet;
* dequeue and discard fragment reassembly header.
@@ -1228,10 +1210,6 @@
return (m);
dropfrag:
-#ifdef IPDIVERT
- *divinfo = 0;
- *divert_rule = 0;
-#endif
ipstat.ips_fragdropped++;
if (fp != NULL)
fp->ipq_nfrags--;
==== //depot/projects/netperf/sys/netinet/ip_output.c#19 (text+ko) ====
@@ -90,6 +90,7 @@
#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",\
@@ -160,7 +161,6 @@
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) {
@@ -170,10 +170,6 @@
m0->_m_tag_id);
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;
@@ -819,11 +815,13 @@
}
#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
@@ -840,7 +838,7 @@
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) {
==== //depot/projects/netperf/sys/netinet/ip_var.h#14 (text+ko) ====
@@ -65,8 +65,6 @@
struct mbuf *ipq_frags; /* to ip headers of fragments */
struct in_addr ipq_src,ipq_dst;
u_char ipq_nfrags; /* # frags in this packet */
- u_int32_t ipq_div_info; /* ipfw divert port & flags */
- u_int16_t ipq_div_cookie; /* ipfw divert cookie */
struct label *ipq_label; /* MAC label */
};
#endif /* _KERNEL */
@@ -198,14 +196,6 @@
extern void (*rsvp_input_p)(struct mbuf *m, int off);
-#ifdef IPDIVERT
-void div_init(void);
-void div_input(struct mbuf *, int);
-void div_ctlinput(int, struct sockaddr *, void *);
-void divert_packet(struct mbuf *m, int incoming, int port, int rule);
-extern struct pr_usrreqs div_usrreqs;
-#endif
-
#ifdef PFIL_HOOKS
extern struct pfil_head inet_pfil_hook;
#endif
More information about the p4-projects
mailing list