Hiya,
* Schvberle Daniel <[EMAIL PROTECTED]> [2005-10-10 14:50]:
> Finally I got around to testing mbuf tag merging patch by Henning
> that Theo suggested.
cool.
> Some new conslusions:
> - mbus tag merging patch helps in all cases and especially
> with the integrated NIC and i386 mp kernel -> almost the same
> performance as i386 sp kernel
wonderful. Thanks for testing that. since the diff itself never went to
any public place before I'll include it below.
What does it do? well, it changes the way pf uses mbuf tags. now,
pf uses 6 distinct mbuf tags for various things, like, altq, the
tag/tagged stuff, marking redirected-to-localhost packets and so on.
They are looked up and attached when needed.
With the diff, pf only uses one mbuf tag with a little structure in the
data part containing the information from the previously dictinct mbuf
tags. we look the tag up once, unconditionally and early and then just
carry a pointer to it around. This makes the code easier, and saves
quite some mbuf tag lookups. the lookups are not free of course, and
the entire mbuf tags are only cheap when there are not too many in use,
since they are just a linked list attached to an mbuf, so the fewer
mbuf tags attached to an mbuf the better the performance.
I really wrote this diff to make the code easier, knowing that there
should be a slight performance gain, great that the latter has been
proven now. there is some more easyfication potential after this is in.
btw, the same should to be done for ipsec later, it uses 6
distinct tags too.
Index: netinet/tcp_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.190
diff -u -p -r1.190 tcp_input.c
--- netinet/tcp_input.c 11 Aug 2005 11:39:36 -0000 1.190
+++ netinet/tcp_input.c 4 Oct 2005 13:00:26 -0000
@@ -604,19 +604,25 @@ findpcb:
break;
}
if (inp == 0) {
+ int inpl_flags = 0;
+#if NPF > 0
+ struct pf_mtag *t;
+
+ if ((t = pf_find_mtag(m)) != NULL &&
+ t->flags & PF_TAG_TRANSLATE_LOCALHOST)
+ inpl_flags = INPLOOKUP_WILDCARD;
+#endif
++tcpstat.tcps_pcbhashmiss;
switch (af) {
#ifdef INET6
case AF_INET6:
inp = in6_pcblookup_listen(&tcbtable,
- &ip6->ip6_dst, th->th_dport, m_tag_find(m,
- PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);
+ &ip6->ip6_dst, th->th_dport, inpl_flags);
break;
#endif /* INET6 */
case AF_INET:
inp = in_pcblookup_listen(&tcbtable,
- ip->ip_dst, th->th_dport, m_tag_find(m,
- PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);
+ ip->ip_dst, th->th_dport, inpl_flags);
break;
}
/*
Index: netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.68
diff -u -p -r1.68 ip_icmp.c
--- netinet/ip_icmp.c 31 Jul 2005 03:30:55 -0000 1.68
+++ netinet/ip_icmp.c 4 Oct 2005 13:00:26 -0000
@@ -134,8 +134,10 @@ icmp_do_error(struct mbuf *n, int type,
unsigned oiplen = oip->ip_hl << 2;
struct icmp *icp;
struct mbuf *m;
- struct m_tag *mtag;
unsigned icmplen, mblen;
+#if NPF > 0
+ struct pf_mtag *mtag;
+#endif
#ifdef ICMPPRINTFS
if (icmpprintfs)
@@ -251,13 +253,14 @@ icmp_do_error(struct mbuf *n, int type,
nip->ip_p = IPPROTO_ICMP;
nip->ip_src = oip->ip_src;
nip->ip_dst = oip->ip_dst;
- /* move PF_GENERATED m_tag to new packet, if it exists */
- mtag = m_tag_find(n, PACKET_TAG_PF_GENERATED, NULL);
- if (mtag != NULL) {
- m_tag_unlink(n, mtag);
- m_tag_prepend(m, mtag);
+#if NPF > 0
+ /* move PF_GENERATED to new packet, if existant XXX preserve more? */
+ if ((mtag = pf_find_mtag(n)) != NULL &&
+ mtag->flags & PF_TAG_GENERATED) {
+ mtag = pf_get_tag(m);
+ mtag->flags |= PF_TAG_GENERATED;
}
-
+#endif
m_freem(n);
return (m);
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.104
diff -u -p -r1.104 udp_usrreq.c
--- netinet/udp_usrreq.c 27 May 2005 04:55:28 -0000 1.104
+++ netinet/udp_usrreq.c 4 Oct 2005 13:00:27 -0000
@@ -525,17 +525,23 @@ udp_input(struct mbuf *m, ...)
inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport);
if (inp == 0) {
+ int inpl_reverse = 0;
+#if NPF > 0
+ struct pf_mtag *t;
+
+ if ((t = pf_find_mtag(m)) != NULL &&
+ t->flags & PF_TAG_TRANSLATE_LOCALHOST)
+ inpl_reverse = 1;
+#endif
++udpstat.udps_pcbhashmiss;
#ifdef INET6
if (ip6) {
inp = in6_pcblookup_listen(&udbtable,
- &ip6->ip6_dst, uh->uh_dport, m_tag_find(m,
- PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);
+ &ip6->ip6_dst, uh->uh_dport, inpl_reverse);
} else
#endif /* INET6 */
inp = in_pcblookup_listen(&udbtable,
- ip->ip_dst, uh->uh_dport, m_tag_find(m,
- PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);
+ ip->ip_dst, uh->uh_dport, inpl_reverse);
if (inp == 0) {
udpstat.udps_noport++;
if (m->m_flags & (M_BCAST | M_MCAST)) {
Index: sys/mbuf.h
===================================================================
RCS file: /cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.82
diff -u -p -r1.82 mbuf.h
--- sys/mbuf.h 26 May 2005 01:49:15 -0000 1.82
+++ sys/mbuf.h 4 Oct 2005 13:00:27 -0000
@@ -585,12 +585,7 @@ struct m_tag *m_tag_next(struct mbuf *,
#define PACKET_TAG_GIF 8 /* GIF processing done */
#define PACKET_TAG_GRE 9 /* GRE processing done */
#define PACKET_TAG_IN_PACKET_CHECKSUM 10 /* NIC checksumming done */
-#define PACKET_TAG_PF_GENERATED 11 /* PF generated,
pass always */
-#define PACKET_TAG_PF_ROUTED 12 /* PF routed, no route loops
*/
-#define PACKET_TAG_PF_FRAGCACHE 13 /* PF fragment
cached */
-#define PACKET_TAG_PF_QID 14 /* PF queue id */
-#define PACKET_TAG_PF_TAG 15 /* PF tags */
-#define PACKET_TAG_PF_TRANSLATE_LOCALHOST 16 /* translated to localhost */
+#define PACKET_TAG_PF 11 /* PF */
#define PACKET_TAG_DLT 17 /* data link layer type */
#ifdef MBTYPES
Index: altq/altq_cbq.c
===================================================================
RCS file: /cvs/src/sys/altq/altq_cbq.c,v
retrieving revision 1.18
diff -u -p -r1.18 altq_cbq.c
--- altq/altq_cbq.c 14 Jan 2004 08:42:23 -0000 1.18
+++ altq/altq_cbq.c 4 Oct 2005 13:00:27 -0000
@@ -441,7 +441,7 @@ cbq_enqueue(struct ifaltq *ifq, struct m
{
cbq_state_t *cbqp = (cbq_state_t *)ifq->altq_disc;
struct rm_class *cl;
- struct m_tag *t;
+ struct pf_mtag *t;
int len;
/* grab class set by classifier */
@@ -452,9 +452,9 @@ cbq_enqueue(struct ifaltq *ifq, struct m
m_freem(m);
return (ENOBUFS);
}
- t = m_tag_find(m, PACKET_TAG_PF_QID, NULL);
+ t = pf_find_mtag(m);
if (t == NULL ||
- (cl = clh_to_clp(cbqp, ((struct altq_tag *)(t+1))->qid)) == NULL) {
+ (cl = clh_to_clp(cbqp, t->qid)) == NULL) {
cl = cbqp->ifnp.default_;
if (cl == NULL) {
m_freem(m);
Index: altq/altq_hfsc.c
===================================================================
RCS file: /cvs/src/sys/altq/altq_hfsc.c,v
retrieving revision 1.21
diff -u -p -r1.21 altq_hfsc.c
--- altq/altq_hfsc.c 14 Jan 2004 08:42:23 -0000 1.21
+++ altq/altq_hfsc.c 4 Oct 2005 13:00:28 -0000
@@ -618,7 +618,7 @@ hfsc_enqueue(struct ifaltq *ifq, struct
{
struct hfsc_if *hif = (struct hfsc_if *)ifq->altq_disc;
struct hfsc_class *cl;
- struct m_tag *t;
+ struct pf_mtag *t;
int len;
/* grab class set by classifier */
@@ -629,9 +629,9 @@ hfsc_enqueue(struct ifaltq *ifq, struct
m_freem(m);
return (ENOBUFS);
}
- t = m_tag_find(m, PACKET_TAG_PF_QID, NULL);
+ t = pf_find_mtag(m);
if (t == NULL ||
- (cl = clh_to_clp(hif, ((struct altq_tag *)(t+1))->qid)) == NULL ||
+ (cl = clh_to_clp(hif, t->qid)) == NULL ||
is_a_parent_class(cl)) {
cl = hif->hif_defaultclass;
if (cl == NULL) {
Index: altq/altq_priq.c
===================================================================
RCS file: /cvs/src/sys/altq/altq_priq.c,v
retrieving revision 1.17
diff -u -p -r1.17 altq_priq.c
--- altq/altq_priq.c 14 Jan 2004 08:42:23 -0000 1.17
+++ altq/altq_priq.c 4 Oct 2005 13:00:28 -0000
@@ -396,7 +396,7 @@ priq_enqueue(struct ifaltq *ifq, struct
{
struct priq_if *pif = (struct priq_if *)ifq->altq_disc;
struct priq_class *cl;
- struct m_tag *t;
+ struct pf_mtag *t;
int len;
/* grab class set by classifier */
@@ -407,9 +407,9 @@ priq_enqueue(struct ifaltq *ifq, struct
m_freem(m);
return (ENOBUFS);
}
- t = m_tag_find(m, PACKET_TAG_PF_QID, NULL);
+ t = pf_find_mtag(m);
if (t == NULL ||
- (cl = clh_to_clp(pif, ((struct altq_tag *)(t+1))->qid)) == NULL) {
+ (cl = clh_to_clp(pif, t->qid)) == NULL) {
cl = pif->pif_default;
if (cl == NULL) {
m_freem(m);
Index: altq/altq_red.c
===================================================================
RCS file: /cvs/src/sys/altq/altq_red.c,v
retrieving revision 1.11
diff -u -p -r1.11 altq_red.c
--- altq/altq_red.c 12 May 2003 00:50:12 -0000 1.11
+++ altq/altq_red.c 4 Oct 2005 13:00:28 -0000
@@ -420,39 +420,28 @@ int
mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
{
struct mbuf *m0;
- struct m_tag *t;
- struct altq_tag *at;
- void *hdr;
- int af;
+ struct pf_mtag *t;
- t = m_tag_find(m, PACKET_TAG_PF_QID, NULL);
- if (t == NULL)
+ if ((t = pf_find_mtag(m)) == NULL)
return (0);
- at = (struct altq_tag *)(t + 1);
- if (at == NULL)
- return (0);
-
- af = at->af;
- hdr = at->hdr;
-
- if (af != AF_INET && af != AF_INET6)
+ if (t->af != AF_INET && t->af != AF_INET6)
return (0);
/* verify that pattr_hdr is within the mbuf data */
for (m0 = m; m0 != NULL; m0 = m0->m_next)
- if (((caddr_t)hdr >= m0->m_data) &&
- ((caddr_t)hdr < m0->m_data + m0->m_len))
+ if (((caddr_t)(t->hdr) >= m0->m_data) &&
+ ((caddr_t)(t->hdr) < m0->m_data + m0->m_len))
break;
if (m0 == NULL) {
/* ick, tag info is stale */
return (0);
}
- switch (af) {
+ switch (t->af) {
case AF_INET:
if (flags & REDF_ECN4) {
- struct ip *ip = hdr;
+ struct ip *ip = t->hdr;
u_int8_t otos;
int sum;
@@ -485,7 +474,7 @@ mark_ecn(struct mbuf *m, struct altq_pkt
#ifdef INET6
case AF_INET6:
if (flags & REDF_ECN6) {
- struct ip6_hdr *ip6 = hdr;
+ struct ip6_hdr *ip6 = t->hdr;
u_int32_t flowlabel;
flowlabel = ntohl(ip6->ip6_flow);
Index: altq/if_altq.h
===================================================================
RCS file: /cvs/src/sys/altq/if_altq.h,v
retrieving revision 1.9
diff -u -p -r1.9 if_altq.h
--- altq/if_altq.h 17 Apr 2004 00:09:00 -0000 1.9
+++ altq/if_altq.h 4 Oct 2005 13:00:28 -0000
@@ -92,16 +92,6 @@ struct altq_pktattr {
};
/*
- * mbuf tag to carry a queue id (and hints for ECN).
- */
-struct altq_tag {
- u_int32_t qid; /* queue id */
- /* hints for ecn */
- int af; /* address family */
- void *hdr; /* saved header position in mbuf */
-};
-
-/*
* a token-bucket regulator limits the rate that a network driver can
* dequeue packets from the output queue.
* modern cards are able to buffer a large amount of packets and dequeue
Index: net/if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.96
diff -u -p -r1.96 if_ethersubr.c
--- net/if_ethersubr.c 8 Jun 2005 06:55:33 -0000 1.96
+++ net/if_ethersubr.c 4 Oct 2005 13:00:28 -0000
@@ -281,9 +281,14 @@ ether_output(ifp0, m0, dst, rt0)
if (!arpresolve(ac, rt, m, dst, edst))
return (0); /* if not yet resolved */
/* If broadcasting on a simplex interface, loopback a copy */
- if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
- m_tag_find(m, PACKET_TAG_PF_ROUTED, NULL) == NULL)
- mcopy = m_copy(m, 0, (int)M_COPYALL);
+ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) {
+#if NPF > 0
+ struct pf_mtag *t;
+
+ if ((t = pf_find_mtag(m)) == NULL || !t->routed)
+#endif
+ mcopy = m_copy(m, 0, (int)M_COPYALL);
+ }
etype = htons(ETHERTYPE_IP);
break;
#endif
Index: net/if_fddisubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_fddisubr.c,v
retrieving revision 1.46
diff -u -p -r1.46 if_fddisubr.c
--- net/if_fddisubr.c 8 Jun 2005 06:55:33 -0000 1.46
+++ net/if_fddisubr.c 4 Oct 2005 13:00:29 -0000
@@ -203,9 +203,14 @@ fddi_output(ifp0, m0, dst, rt0)
if (!arpresolve(ac, rt, m, dst, edst))
return (0); /* if not yet resolved */
/* If broadcasting on a simplex interface, loopback a copy */
- if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
- m_tag_find(m, PACKET_TAG_PF_ROUTED, NULL) == NULL)
+ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) {
+#if NPF > 0
+ struct pf_mtag *t;
+
+ if ((t = pf_find_mtag(m)) == NULL || !t->routed)
+#endif
mcopy = m_copy(m, 0, (int)M_COPYALL);
+ }
type = htons(ETHERTYPE_IP);
break;
#endif
Index: net/pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.503
diff -u -p -r1.503 pf.c
--- net/pf.c 28 Sep 2005 01:46:32 -0000 1.503
+++ net/pf.c 4 Oct 2005 13:00:31 -0000
@@ -182,9 +182,8 @@ int pf_test_state_icmp(struct pf_stat
void *, struct pf_pdesc *, u_short *);
int pf_test_state_other(struct pf_state **, int,
struct pfi_kif *, struct pf_pdesc *);
-struct pf_tag *pf_get_tag(struct mbuf *);
int pf_match_tag(struct mbuf *, struct pf_rule *,
- struct pf_tag **, int *);
+ struct pf_mtag *, int *);
void pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
int pf_map_addr(u_int8_t, struct pf_rule *,
@@ -195,9 +194,11 @@ int pf_get_sport(sa_family_t,
u_int8_
struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
struct pf_src_node **);
void pf_route(struct mbuf **, struct pf_rule *, int,
- struct ifnet *, struct pf_state *);
+ struct ifnet *, struct pf_state *,
+ struct pf_pdesc *);
void pf_route6(struct mbuf **, struct pf_rule *, int,
- struct ifnet *, struct pf_state *);
+ struct ifnet *, struct pf_state *,
+ struct pf_pdesc *);
int pf_socket_lookup(int, struct pf_pdesc *);
u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t,
sa_family_t);
@@ -211,7 +212,6 @@ int pf_check_proto_cksum(struct mbuf
u_int8_t, sa_family_t);
int pf_addr_wrap_neq(struct pf_addr_wrap *,
struct pf_addr_wrap *);
-static int pf_add_mbuf_tag(struct mbuf *, u_int);
struct pf_state *pf_find_state_recurse(struct pfi_kif *,
struct pf_state_cmp *, u_int8_t);
int pf_src_connlimit(struct pf_state **);
@@ -988,12 +988,13 @@ pf_src_tree_remove_state(struct pf_state
void
pf_unlink_state(struct pf_state *cur)
{
- if (cur->src.state == PF_TCPS_PROXY_DST)
+ if (cur->src.state == PF_TCPS_PROXY_DST) {
pf_send_tcp(cur->rule.ptr, cur->af,
&cur->ext.addr, &cur->lan.addr,
cur->ext.port, cur->lan.port,
cur->src.seqhi, cur->src.seqlo + 1,
TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
+ }
RB_REMOVE(pf_state_tree_ext_gwy,
&cur->u.s.kif->pfik_ext_gwy, cur);
RB_REMOVE(pf_state_tree_lan_ext,
@@ -1507,7 +1508,8 @@ pf_send_tcp(const struct pf_rule *r, sa_
struct ip6_hdr *h6;
#endif /* INET6 */
struct tcphdr *th;
- char *opt;
+ char *opt;
+ struct pf_mtag *pf_mtag;
/* maximum segment size tcp option */
tlen = sizeof(struct tcphdr);
@@ -1531,35 +1533,20 @@ pf_send_tcp(const struct pf_rule *r, sa_
m = m_gethdr(M_DONTWAIT, MT_HEADER);
if (m == NULL)
return;
- if (tag) {
- struct m_tag *mtag;
-
- mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
- if (mtag == NULL) {
- m_freem(m);
- return;
- }
- m_tag_prepend(m, mtag);
+ if ((pf_mtag = pf_get_mtag(m)) == NULL) {
+ m_freem(m);
+ return;
}
- if (rtag)
- if (pf_tag_packet(m, NULL, rtag)) {
- m_freem(m);
- return;
- }
+ if (tag)
+ pf_mtag->flags |= PF_TAG_GENERATED;
+ pf_mtag->tag = rtag;
+
#ifdef ALTQ
if (r != NULL && r->qid) {
- struct m_tag *mtag;
- struct altq_tag *atag;
-
- mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT);
- if (mtag != NULL) {
- atag = (struct altq_tag *)(mtag + 1);
- atag->qid = r->qid;
- /* add hints for ecn */
- atag->af = af;
- atag->hdr = mtod(m, struct ip *);
- m_tag_prepend(m, mtag);
- }
+ pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pf_mtag->af = af;
+ pf_mtag->hdr = mtod(m, struct ip *);
}
#endif /* ALTQ */
m->m_data += max_linkhdr;
@@ -1669,32 +1656,21 @@ void
pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
struct pf_rule *r)
{
- struct m_tag *mtag;
+ struct pf_mtag *pf_mtag;
struct mbuf *m0;
- mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
- if (mtag == NULL)
- return;
m0 = m_copy(m, 0, M_COPYALL);
- if (m0 == NULL) {
- m_tag_free(mtag);
+
+ if ((pf_mtag = pf_get_mtag(m0)) == NULL)
return;
- }
- m_tag_prepend(m0, mtag);
+ pf_mtag->flags |= PF_TAG_GENERATED;
#ifdef ALTQ
if (r->qid) {
- struct altq_tag *atag;
-
- mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT);
- if (mtag != NULL) {
- atag = (struct altq_tag *)(mtag + 1);
- atag->qid = r->qid;
- /* add hints for ecn */
- atag->af = af;
- atag->hdr = mtod(m0, struct ip *);
- m_tag_prepend(m0, mtag);
- }
+ pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pf_mtag->af = af;
+ pf_mtag->hdr = mtod(m0, struct ip *);
}
#endif /* ALTQ */
@@ -1809,48 +1785,55 @@ pf_match_gid(u_int8_t op, gid_t a1, gid_
return (pf_match(op, a1, a2, g));
}
-struct pf_tag *
-pf_get_tag(struct mbuf *m)
+struct pf_mtag *
+pf_find_mtag(struct mbuf *m)
{
struct m_tag *mtag;
- if ((mtag = m_tag_find(m, PACKET_TAG_PF_TAG, NULL)) != NULL)
- return ((struct pf_tag *)(mtag + 1));
- else
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL)
return (NULL);
+
+ return ((struct pf_mtag *)(mtag + 1));
}
-int
-pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_tag **pftag, int
*tag)
+struct pf_mtag *
+pf_get_mtag(struct mbuf *m)
{
- if (*tag == -1) { /* find mbuf tag */
- *pftag = pf_get_tag(m);
- if (*pftag != NULL)
- *tag = (*pftag)->tag;
- else
- *tag = 0;
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL) {
+ mtag = m_tag_get(PACKET_TAG_PF, sizeof(struct pf_mtag),
+ M_NOWAIT);
+ if (mtag == NULL)
+ return (NULL);
+ bzero(mtag + 1, sizeof(struct pf_mtag));
+ m_tag_prepend(m, mtag);
}
+ return ((struct pf_mtag *)(mtag + 1));
+}
+
+int
+pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_mtag *pf_mtag,
+ int *tag)
+{
+ if (*tag == -1)
+ *tag = pf_mtag->tag;
+
return ((!r->match_tag_not && r->match_tag == *tag) ||
(r->match_tag_not && r->match_tag != *tag));
}
int
-pf_tag_packet(struct mbuf *m, struct pf_tag *pftag, int tag)
+pf_tag_packet(struct mbuf *m, struct pf_mtag *pf_mtag, int tag)
{
- struct m_tag *mtag;
-
if (tag <= 0)
return (0);
- if (pftag == NULL) {
- mtag = m_tag_get(PACKET_TAG_PF_TAG, sizeof(*pftag), M_NOWAIT);
- if (mtag == NULL)
+ if (pf_mtag == NULL)
+ if ((pf_mtag = pf_get_mtag(m)) == NULL)
return (1);
- ((struct pf_tag *)(mtag + 1))->tag = tag;
- m_tag_prepend(m, mtag);
- } else
- pftag->tag = tag;
+ pf_mtag->tag = tag;
return (0);
}
@@ -2309,7 +2292,6 @@ pf_match_translation(struct pf_pdesc *pd
{
struct pf_rule *r, *rm = NULL;
struct pf_ruleset *ruleset = NULL;
- struct pf_tag *pftag = NULL;
int tag = -1;
int asd = 0;
@@ -2352,7 +2334,7 @@ pf_match_translation(struct pf_pdesc *pd
!pf_match_port(dst->port_op, dst->port[0],
dst->port[1], dport))
r = r->skip[PF_SKIP_DST_PORT].ptr;
- else if (r->match_tag && !pf_match_tag(m, r, &pftag, &tag))
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
@@ -2369,7 +2351,7 @@ pf_match_translation(struct pf_pdesc *pd
if (r == NULL)
pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r, NULL);
}
- if (pf_tag_packet(m, pftag, tag))
+ if (pf_tag_packet(m, pd->pf_mtag, tag))
return (NULL);
if (rm != NULL && (rm->action == PF_NONAT ||
rm->action == PF_NORDR || rm->action == PF_NOBINAT))
@@ -2775,7 +2757,6 @@ pf_test_tcp(struct pf_rule **rm, struct
struct pf_src_node *nsn = NULL;
u_short reason;
int rewrite = 0;
- struct pf_tag *pftag = NULL;
int tag = -1;
u_int16_t mss = tcp_mssdflt;
int asd = 0;
@@ -2855,7 +2836,7 @@ pf_test_tcp(struct pf_rule **rm, struct
r = TAILQ_NEXT(r, entries);
else if (r->prob && r->prob <= arc4random())
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, &pftag, &tag))
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
pf_osfp_fingerprint(pd, m, off, th), r->os_fingerprint))
@@ -2931,7 +2912,7 @@ pf_test_tcp(struct pf_rule **rm, struct
if (r->action == PF_DROP)
return (PF_DROP);
- if (pf_tag_packet(m, pftag, tag)) {
+ if (pf_tag_packet(m, pd->pf_mtag, tag)) {
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -3150,7 +3131,6 @@ pf_test_udp(struct pf_rule **rm, struct
struct pf_src_node *nsn = NULL;
u_short reason;
int rewrite = 0;
- struct pf_tag *pftag = NULL;
int tag = -1;
int asd = 0;
@@ -3227,7 +3207,7 @@ pf_test_udp(struct pf_rule **rm, struct
r = TAILQ_NEXT(r, entries);
else if (r->prob && r->prob <= arc4random())
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, &pftag, &tag))
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
@@ -3288,7 +3268,7 @@ pf_test_udp(struct pf_rule **rm, struct
if (r->action == PF_DROP)
return (PF_DROP);
- if (pf_tag_packet(m, pftag, tag)) {
+ if (pf_tag_packet(m, pd->pf_mtag, tag)) {
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -3427,7 +3407,6 @@ pf_test_icmp(struct pf_rule **rm, struct
sa_family_t af = pd->af;
u_int8_t icmptype, icmpcode;
int state_icmp = 0;
- struct pf_tag *pftag = NULL;
int tag = -1;
#ifdef INET6
int rewrite = 0;
@@ -3553,7 +3532,7 @@ pf_test_icmp(struct pf_rule **rm, struct
r = TAILQ_NEXT(r, entries);
else if (r->prob && r->prob <= arc4random())
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, &pftag, &tag))
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
@@ -3594,7 +3573,7 @@ pf_test_icmp(struct pf_rule **rm, struct
if (r->action != PF_PASS)
return (PF_DROP);
- if (pf_tag_packet(m, pftag, tag)) {
+ if (pf_tag_packet(m, pd->pf_mtag, tag)) {
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -3730,7 +3709,6 @@ pf_test_other(struct pf_rule **rm, struc
struct pf_addr *saddr = pd->src, *daddr = pd->dst;
sa_family_t af = pd->af;
u_short reason;
- struct pf_tag *pftag = NULL;
int tag = -1;
int asd = 0;
@@ -3807,7 +3785,7 @@ pf_test_other(struct pf_rule **rm, struc
r = TAILQ_NEXT(r, entries);
else if (r->prob && r->prob <= arc4random())
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, &pftag, &tag))
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
r = TAILQ_NEXT(r, entries);
else if (r->os_fingerprint != PF_OSFP_ANY)
r = TAILQ_NEXT(r, entries);
@@ -3876,7 +3854,7 @@ pf_test_other(struct pf_rule **rm, struc
if (r->action != PF_PASS)
return (PF_DROP);
- if (pf_tag_packet(m, pftag, tag)) {
+ if (pf_tag_packet(m, pd->pf_mtag, tag)) {
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -3994,7 +3972,6 @@ pf_test_fragment(struct pf_rule **rm, in
struct pf_ruleset *ruleset = NULL;
sa_family_t af = pd->af;
u_short reason;
- struct pf_tag *pftag = NULL;
int tag = -1;
int asd = 0;
@@ -4021,7 +3998,7 @@ pf_test_fragment(struct pf_rule **rm, in
r = TAILQ_NEXT(r, entries);
else if (r->prob && r->prob <= arc4random())
r = TAILQ_NEXT(r, entries);
- else if (r->match_tag && !pf_match_tag(m, r, &pftag, &tag))
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
r = TAILQ_NEXT(r, entries);
else {
if (r->anchor == NULL) {
@@ -4052,7 +4029,7 @@ pf_test_fragment(struct pf_rule **rm, in
if (r->action != PF_PASS)
return (PF_DROP);
- if (pf_tag_packet(m, pftag, tag)) {
+ if (pf_tag_packet(m, pd->pf_mtag, tag)) {
REASON_SET(&reason, PFRES_MEMORY);
return (PF_DROP);
}
@@ -5355,7 +5332,7 @@ pf_rtlabel_match(struct pf_addr *addr, s
#ifdef INET
void
pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
- struct pf_state *s)
+ struct pf_state *s, struct pf_pdesc *pd)
{
struct mbuf *m0, *m1;
struct m_tag *mtag;
@@ -5372,22 +5349,10 @@ pf_route(struct mbuf **m, struct pf_rule
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
panic("pf_route: invalid parameters");
- if ((mtag = m_tag_find(*m, PACKET_TAG_PF_ROUTED, NULL)) == NULL) {
- if ((mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 1, M_NOWAIT)) ==
- NULL) {
- m0 = *m;
- *m = NULL;
- goto bad;
- }
- *(char *)(mtag + 1) = 1;
- m_tag_prepend(*m, mtag);
- } else {
- if (*(char *)(mtag + 1) > 3) {
- m0 = *m;
- *m = NULL;
- goto bad;
- }
- (*(char *)(mtag + 1))++;
+ if (pd->pf_mtag->routed++ > 3) {
+ m0 = *m;
+ *m = NULL;
+ goto bad;
}
if (r->rt == PF_DUPTO) {
@@ -5559,10 +5524,9 @@ bad:
#ifdef INET6
void
pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
- struct pf_state *s)
+ struct pf_state *s, struct pf_pdesc *pd)
{
struct mbuf *m0;
- struct m_tag *mtag;
struct route_in6 ip6route;
struct route_in6 *ro;
struct sockaddr_in6 *dst;
@@ -5576,22 +5540,10 @@ pf_route6(struct mbuf **m, struct pf_rul
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
panic("pf_route6: invalid parameters");
- if ((mtag = m_tag_find(*m, PACKET_TAG_PF_ROUTED, NULL)) == NULL) {
- if ((mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 1, M_NOWAIT)) ==
- NULL) {
- m0 = *m;
- *m = NULL;
- goto bad;
- }
- *(char *)(mtag + 1) = 1;
- m_tag_prepend(*m, mtag);
- } else {
- if (*(char *)(mtag + 1) > 3) {
- m0 = *m;
- *m = NULL;
- goto bad;
- }
- (*(char *)(mtag + 1))++;
+ if (pd->pf_mtag->routed++ > 3) {
+ m0 = *m;
+ *m = NULL;
+ goto bad;
}
if (r->rt == PF_DUPTO) {
@@ -5617,12 +5569,9 @@ pf_route6(struct mbuf **m, struct pf_rul
dst->sin6_len = sizeof(*dst);
dst->sin6_addr = ip6->ip6_dst;
- /* Cheat. */
+ /* Cheat. XXX why only in the v6 case??? */
if (r->rt == PF_FASTROUTE) {
- mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
- if (mtag == NULL)
- goto bad;
- m_tag_prepend(m0, mtag);
+ pd->pf_mtag->flags |= PF_TAG_GENERATED;
ip6_output(m0, NULL, NULL, 0, NULL, NULL);
return;
}
@@ -5780,20 +5729,6 @@ pf_check_proto_cksum(struct mbuf *m, int
return (0);
}
-static int
-pf_add_mbuf_tag(struct mbuf *m, u_int tag)
-{
- struct m_tag *mtag;
-
- if (m_tag_find(m, tag, NULL) != NULL)
- return (0);
- mtag = m_tag_get(tag, 0, M_NOWAIT);
- if (mtag == NULL)
- return (1);
- m_tag_prepend(m, mtag);
- return (0);
-}
-
#ifdef INET
int
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
@@ -5809,8 +5744,16 @@ pf_test(int dir, struct ifnet *ifp, stru
struct pf_pdesc pd;
int off, dirndx, pqid = 0;
- if (!pf_status.running ||
- (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
+ if (!pf_status.running)
+ return (PF_PASS);
+
+ memset(&pd, 0, sizeof(pd));
+ if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_test: pf_get_mtag returned NULL\n"));
+ return (PF_DROP);
+ }
+ if (pd.pf_mtag->flags & PF_TAG_GENERATED)
return (PF_PASS);
if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
@@ -5830,7 +5773,6 @@ pf_test(int dir, struct ifnet *ifp, stru
panic("non-M_PKTHDR is passed to pf_test");
#endif /* DIAGNOSTIC */
- memset(&pd, 0, sizeof(pd));
if (m->m_pkthdr.len < (int)sizeof(*h)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_SHORT);
@@ -6001,25 +5943,17 @@ done:
}
if (s && s->tag)
- pf_tag_packet(m, pf_get_tag(m), s->tag);
+ pf_tag_packet(m, pd.pf_mtag, s->tag);
#ifdef ALTQ
if (action == PF_PASS && r->qid) {
- struct m_tag *mtag;
- struct altq_tag *atag;
-
- mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT);
- if (mtag != NULL) {
- atag = (struct altq_tag *)(mtag + 1);
- if (pqid || pd.tos == IPTOS_LOWDELAY)
- atag->qid = r->pqid;
- else
- atag->qid = r->qid;
- /* add hints for ecn */
- atag->af = AF_INET;
- atag->hdr = h;
- m_tag_prepend(m, mtag);
- }
+ if (pqid || pd.tos == IPTOS_LOWDELAY)
+ pd.pf_mtag->qid = r->pqid;
+ else
+ pd.pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pd.pf_mtag->af = AF_INET;
+ pd.pf_mtag->hdr = h;
}
#endif /* ALTQ */
@@ -6032,11 +5966,8 @@ done:
pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
(s->nat_rule.ptr->action == PF_RDR ||
s->nat_rule.ptr->action == PF_BINAT) &&
- (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET &&
- pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_MEMORY);
- }
+ (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ pd.pf_mtag->flags |= PF_TAG_TRANSLATE_LOCALHOST;
if (log) {
struct pf_rule *lr;
@@ -6121,7 +6052,7 @@ done:
action = PF_PASS;
} else if (r->rt)
/* pf_route can free the mbuf causing *m0 to become NULL */
- pf_route(m0, r, dir, ifp, s);
+ pf_route(m0, r, dir, ifp, s, &pd);
return (action);
}
@@ -6142,8 +6073,16 @@ pf_test6(int dir, struct ifnet *ifp, str
struct pf_pdesc pd;
int off, terminal = 0, dirndx;
- if (!pf_status.running ||
- (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL))
+ if (!pf_status.running)
+ return (PF_PASS);
+
+ memset(&pd, 0, sizeof(pd));
+ if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_test6: pf_get_mtag returned NULL\n"));
+ return (PF_DROP);
+ }
+ if (pd.pf_mtag->flags & PF_TAG_GENERATED)
return (PF_PASS);
if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
@@ -6163,7 +6102,6 @@ pf_test6(int dir, struct ifnet *ifp, str
panic("non-M_PKTHDR is passed to pf_test6");
#endif /* DIAGNOSTIC */
- memset(&pd, 0, sizeof(pd));
if (m->m_pkthdr.len < (int)sizeof(*h)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_SHORT);
@@ -6351,25 +6289,17 @@ done:
/* XXX handle IPv6 options, if not allowed. not implemented. */
if (s && s->tag)
- pf_tag_packet(m, pf_get_tag(m), s->tag);
+ pf_tag_packet(m, pd.pf_mtag, s->tag);
#ifdef ALTQ
if (action == PF_PASS && r->qid) {
- struct m_tag *mtag;
- struct altq_tag *atag;
-
- mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT);
- if (mtag != NULL) {
- atag = (struct altq_tag *)(mtag + 1);
- if (pd.tos == IPTOS_LOWDELAY)
- atag->qid = r->pqid;
- else
- atag->qid = r->qid;
- /* add hints for ecn */
- atag->af = AF_INET6;
- atag->hdr = h;
- m_tag_prepend(m, mtag);
- }
+ if (pd.tos == IPTOS_LOWDELAY)
+ pd.pf_mtag->qid = r->pqid;
+ else
+ pd.pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pd.pf_mtag->af = AF_INET6;
+ pd.pf_mtag->hdr = h;
}
#endif /* ALTQ */
@@ -6377,11 +6307,8 @@ done:
pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
(s->nat_rule.ptr->action == PF_RDR ||
s->nat_rule.ptr->action == PF_BINAT) &&
- IN6_IS_ADDR_LOOPBACK(&pd.dst->v6) &&
- pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
- action = PF_DROP;
- REASON_SET(&reason, PFRES_MEMORY);
- }
+ IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))
+ pd.pf_mtag->flags |= PF_TAG_TRANSLATE_LOCALHOST;
if (log) {
struct pf_rule *lr;
@@ -6466,7 +6393,7 @@ done:
action = PF_PASS;
} else if (r->rt)
/* pf_route6 can free the mbuf causing *m0 to become NULL */
- pf_route6(m0, r, dir, ifp, s);
+ pf_route6(m0, r, dir, ifp, s, &pd);
return (action);
}
Index: net/pf_norm.c
===================================================================
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.102
diff -u -p -r1.102 pf_norm.c
--- net/pf_norm.c 6 Aug 2005 12:11:09 -0000 1.102
+++ net/pf_norm.c 4 Oct 2005 13:00:31 -0000
@@ -931,15 +931,13 @@ pf_normalize_ip(struct mbuf **m0, int di
/* non-buffering fragment cache (drops or masks overlaps) */
int nomem = 0;
- if (dir == PF_OUT) {
- if (m_tag_find(m, PACKET_TAG_PF_FRAGCACHE, NULL) !=
- NULL) {
- /* Already passed the fragment cache in the
- * input direction. If we continued, it would
- * appear to be a dup and would be dropped.
- */
- goto fragment_pass;
- }
+ if (dir == PF_OUT && pd->pf_mtag->flags & PF_TAG_FRAGCACHE) {
+ /*
+ * Already passed the fragment cache in the
+ * input direction. If we continued, it would
+ * appear to be a dup and would be dropped.
+ */
+ goto fragment_pass;
}
frag = pf_find_fragment(h, &pf_cache_tree);
@@ -960,14 +958,9 @@ pf_normalize_ip(struct mbuf **m0, int di
goto drop;
}
- if (dir == PF_IN) {
- struct m_tag *mtag;
+ if (dir == PF_IN)
+ pd->pf_mtag->flags |= PF_TAG_FRAGCACHE;
- mtag = m_tag_get(PACKET_TAG_PF_FRAGCACHE, 0, M_NOWAIT);
- if (mtag == NULL)
- goto no_mem;
- m_tag_prepend(m, mtag);
- }
if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
goto drop;
goto fragment_pass;
Index: net/pfvar.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar.h,v
retrieving revision 1.230
diff -u -p -r1.230 pfvar.h
--- net/pfvar.h 28 Sep 2005 01:46:33 -0000 1.230
+++ net/pfvar.h 4 Oct 2005 13:00:32 -0000
@@ -936,6 +936,7 @@ struct pf_pdesc {
struct pf_addr *dst;
struct ether_header
*eh;
+ struct pf_mtag *pf_mtag;
u_int16_t *ip_sum;
u_int32_t p_len; /* total length of payload */
u_int16_t flags; /* Let SCRUB trigger behavior in
@@ -1139,6 +1140,19 @@ struct pf_altq {
u_int32_t qid; /* return value */
};
+#define PF_TAG_GENERATED 0x01
+#define PF_TAG_FRAGCACHE 0x02
+#define PF_TAG_TRANSLATE_LOCALHOST 0x04
+
+struct pf_mtag {
+ void *hdr; /* saved hdr pos in mbuf, for ECN */
+ u_int32_t qid; /* queue id */
+ u_int16_t tag; /* tag id */
+ u_int8_t flags;
+ u_int8_t routed;
+ sa_family_t af; /* for ECN */
+};
+
struct pf_tag {
u_int16_t tag; /* tag id */
};
@@ -1561,14 +1575,16 @@ int pfi_get_ifaces(const char *, struc
int pfi_set_flags(const char *, int);
int pfi_clear_flags(const char *, int);
-u_int16_t pf_tagname2tag(char *);
-void pf_tag2tagname(u_int16_t, char *);
-void pf_tag_ref(u_int16_t);
-void pf_tag_unref(u_int16_t);
-int pf_tag_packet(struct mbuf *, struct pf_tag *, int);
-u_int32_t pf_qname2qid(char *);
-void pf_qid2qname(u_int32_t, char *);
-void pf_qid_unref(u_int32_t);
+u_int16_t pf_tagname2tag(char *);
+void pf_tag2tagname(u_int16_t, char *);
+void pf_tag_ref(u_int16_t);
+void pf_tag_unref(u_int16_t);
+int pf_tag_packet(struct mbuf *, struct pf_mtag *, int);
+u_int32_t pf_qname2qid(char *);
+void pf_qid2qname(u_int32_t, char *);
+void pf_qid_unref(u_int32_t);
+struct pf_mtag *pf_find_mtag(struct mbuf *);
+struct pf_mtag *pf_get_mtag(struct mbuf *);
extern struct pf_status pf_status;
extern struct pool pf_frent_pl, pf_frag_pl;