Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144842989
D6786.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D6786.diff
View Options
Index: head/sbin/pfctl/parse.y
===================================================================
--- head/sbin/pfctl/parse.y
+++ head/sbin/pfctl/parse.y
@@ -217,6 +217,8 @@
#define FOM_TOS 0x04
#define FOM_KEEP 0x08
#define FOM_SRCTRACK 0x10
+#define FOM_SETPRIO 0x0400
+#define FOM_PRIO 0x2000
struct node_uid *uid;
struct node_gid *gid;
struct {
@@ -240,6 +242,8 @@
char *match_tag;
u_int8_t match_tag_not;
u_int rtableid;
+ u_int8_t prio;
+ u_int8_t set_prio[2];
struct {
struct node_host *addr;
u_int16_t port;
@@ -453,7 +457,7 @@
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
%token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL
-%token LOAD RULESET_OPTIMIZATION
+%token LOAD RULESET_OPTIMIZATION PRIO
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY
%token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
@@ -468,7 +472,7 @@
%type <v.i> no dir af fragcache optimizer
%type <v.i> sourcetrack flush unaryop statelock
%type <v.b> action nataction natpasslog scrubaction
-%type <v.b> flags flag blockspec
+%type <v.b> flags flag blockspec prio
%type <v.range> portplain portstar portrange
%type <v.hashkey> hashkey
%type <v.proto> proto proto_list proto_item
@@ -504,6 +508,7 @@
%type <v.codel_opts> codelopts_list codelopts_item codel_opts
%type <v.queue_bwspec> bandwidth
%type <v.filter_opts> filter_opts filter_opt filter_opts_l
+%type <v.filter_opts> filter_sets filter_set filter_sets_l
%type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l
%type <v.queue_opts> queue_opts queue_opt queue_opts_l
%type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l
@@ -889,6 +894,17 @@
YYERROR;
}
r.match_tag_not = $9.match_tag_not;
+ if ($9.marker & FOM_PRIO) {
+ if ($9.prio == 0)
+ r.prio = PF_PRIO_ZERO;
+ else
+ r.prio = $9.prio;
+ }
+ if ($9.marker & FOM_SETPRIO) {
+ r.set_prio[0] = $9.set_prio[0];
+ r.set_prio[1] = $9.set_prio[1];
+ r.scrub_flags |= PFSTATE_SETPRIO;
+ }
decide_address_family($8.src.host, &r.af);
decide_address_family($8.dst.host, &r.af);
@@ -2014,6 +2030,18 @@
r.prob = $9.prob;
r.rtableid = $9.rtableid;
+ if ($9.marker & FOM_PRIO) {
+ if ($9.prio == 0)
+ r.prio = PF_PRIO_ZERO;
+ else
+ r.prio = $9.prio;
+ }
+ if ($9.marker & FOM_SETPRIO) {
+ r.set_prio[0] = $9.set_prio[0];
+ r.set_prio[1] = $9.set_prio[1];
+ r.scrub_flags |= PFSTATE_SETPRIO;
+ }
+
r.af = $6;
if ($9.tag)
if (strlcpy(r.tagname, $9.tag,
@@ -2434,6 +2462,18 @@
filter_opts.marker |= FOM_ICMP;
filter_opts.icmpspec = $1;
}
+ | PRIO NUMBER {
+ if (filter_opts.marker & FOM_PRIO) {
+ yyerror("prio cannot be redefined");
+ YYERROR;
+ }
+ if ($2 < 0 || $2 > PF_PRIO_MAX) {
+ yyerror("prio must be 0 - %u", PF_PRIO_MAX);
+ YYERROR;
+ }
+ filter_opts.marker |= FOM_PRIO;
+ filter_opts.prio = $2;
+ }
| TOS tos {
if (filter_opts.marker & FOM_TOS) {
yyerror("tos cannot be redefined");
@@ -2532,6 +2572,42 @@
filter_opts.divert.port = 1; /* some random value */
#endif
}
+ | filter_sets
+ ;
+
+filter_sets : SET '(' filter_sets_l ')' { $$ = filter_opts; }
+ | SET filter_set { $$ = filter_opts; }
+ ;
+
+filter_sets_l : filter_sets_l comma filter_set
+ | filter_set
+ ;
+
+filter_set : prio {
+ if (filter_opts.marker & FOM_SETPRIO) {
+ yyerror("prio cannot be redefined");
+ YYERROR;
+ }
+ filter_opts.marker |= FOM_SETPRIO;
+ filter_opts.set_prio[0] = $1.b1;
+ filter_opts.set_prio[1] = $1.b2;
+ }
+prio : PRIO NUMBER {
+ if ($2 < 0 || $2 > PF_PRIO_MAX) {
+ yyerror("prio must be 0 - %u", PF_PRIO_MAX);
+ YYERROR;
+ }
+ $$.b1 = $$.b2 = $2;
+ }
+ | PRIO '(' NUMBER comma NUMBER ')' {
+ if ($3 < 0 || $3 > PF_PRIO_MAX ||
+ $5 < 0 || $5 > PF_PRIO_MAX) {
+ yyerror("prio must be 0 - %u", PF_PRIO_MAX);
+ YYERROR;
+ }
+ $$.b1 = $3;
+ $$.b2 = $5;
+ }
;
probability : STRING {
@@ -5426,6 +5502,7 @@
{ "overload", OVERLOAD},
{ "pass", PASS},
{ "port", PORT},
+ { "prio", PRIO},
{ "priority", PRIORITY},
{ "priq", PRIQ},
{ "probability", PROBABILITY},
Index: head/sbin/pfctl/pfctl_parser.c
===================================================================
--- head/sbin/pfctl/pfctl_parser.c
+++ head/sbin/pfctl/pfctl_parser.c
@@ -841,6 +841,21 @@
}
if (r->tos)
printf(" tos 0x%2.2x", r->tos);
+ if (r->prio)
+ printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio);
+ if (r->scrub_flags & PFSTATE_SETMASK) {
+ char *comma = "";
+ printf(" set (");
+ if (r->scrub_flags & PFSTATE_SETPRIO) {
+ if (r->set_prio[0] == r->set_prio[1])
+ printf("%s prio %u", comma, r->set_prio[0]);
+ else
+ printf("%s prio(%u, %u)", comma, r->set_prio[0],
+ r->set_prio[1]);
+ comma = ",";
+ }
+ printf(" )");
+ }
if (!r->keep_state && r->action == PF_PASS && !anchor_call[0])
printf(" no state");
else if (r->keep_state == PF_STATE_NORMAL)
Index: head/share/man/man5/pf.conf.5
===================================================================
--- head/share/man/man5/pf.conf.5
+++ head/share/man/man5/pf.conf.5
@@ -28,7 +28,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd July 25, 2015
+.Dd June 9, 2016
.Dt PF.CONF 5
.Os
.Sh NAME
@@ -1785,6 +1785,25 @@
pass in proto tcp to port 25 queue mail
pass in proto tcp to port 22 queue(ssh_bulk, ssh_prio)
.Ed
+.Pp
+.It Cm set prio Ar priority | Pq Ar priority , priority
+Packets matching this rule will be assigned a specific queueing priority.
+Priorities are assigned as integers 0 through 7.
+If the packet is transmitted on a
+.Xr vlan 4
+interface, the queueing priority will be written as the priority
+code point in the 802.1Q VLAN header.
+If two priorities are given, packets which have a TOS of
+.Cm lowdelay
+and TCP ACKs with no data payload will be assigned to the second one.
+.Pp
+For example:
+.Bd -literal -offset indent
+pass in proto tcp to port 25 set prio 2
+pass in proto tcp to port 22 set prio (2, 5)
+.Ed
+.Pp
+
.It Ar tag Aq Ar string
Packets matching this rule will be tagged with the
specified string.
@@ -1845,6 +1864,9 @@
.Bd -literal -offset indent
block in proto icmp probability 20%
.Ed
+.It Ar prio Aq Ar number
+Only match packets which have the given queueing priority assigned.
+.Pp
.El
.Sh ROUTING
If a packet matches a rule with a route option set, the packet filter will
@@ -2831,8 +2853,9 @@
"max-mss" number | "random-id" | "reassemble tcp" |
fragmentation | "allow-opts" |
"label" string | "tag" string | [ ! ] "tagged" string |
+ "set prio" ( number | "(" number [ [ "," ] number ] ")" ) |
"queue" ( string | "(" string [ [ "," ] string ] ")" ) |
- "rtable" number | "probability" number"%"
+ "rtable" number | "probability" number"%" | "prio" number
nat-rule = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
[ "on" ifspec ] [ af ]
Index: head/sys/net/pfvar.h
===================================================================
--- head/sys/net/pfvar.h
+++ head/sys/net/pfvar.h
@@ -540,7 +540,7 @@
u_int16_t max_mss;
u_int16_t tag;
u_int16_t match_tag;
- u_int16_t spare2; /* netgraph */
+ u_int16_t scrub_flags;
struct pf_rule_uid uid;
struct pf_rule_gid gid;
@@ -577,6 +577,10 @@
#define PF_FLUSH 0x01
#define PF_FLUSH_GLOBAL 0x02
u_int8_t flush;
+#define PF_PRIO_ZERO 0xff /* match "prio 0" packets */
+#define PF_PRIO_MAX 7
+ u_int8_t prio;
+ u_int8_t set_prio[2];
struct {
struct pf_addr addr;
@@ -739,6 +743,8 @@
/* was PFSTATE_PFLOW 0x04 */
#define PFSTATE_NOSYNC 0x08
#define PFSTATE_ACK 0x10
+#define PFSTATE_SETPRIO 0x0200
+#define PFSTATE_SETMASK (PFSTATE_SETPRIO)
u_int8_t timeout;
u_int8_t sync_state; /* PFSYNC_S_x */
Index: head/sys/netpfil/pf/pf.c
===================================================================
--- head/sys/netpfil/pf/pf.c
+++ head/sys/netpfil/pf/pf.c
@@ -63,6 +63,7 @@
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_types.h>
+#include <net/if_vlan_var.h>
#include <net/route.h>
#include <net/radix_mpath.h>
#include <net/vnet.h>
@@ -2445,6 +2446,45 @@
pf_send(pfse);
}
+static int
+pf_ieee8021q_setpcp(struct mbuf *m, u_int8_t prio)
+{
+ struct m_tag *mtag;
+
+ KASSERT(prio <= PF_PRIO_MAX,
+ ("%s with invalid pcp", __func__));
+
+ mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_OUT, NULL);
+ if (mtag == NULL) {
+ mtag = m_tag_alloc(MTAG_8021Q, MTAG_8021Q_PCP_OUT,
+ sizeof(uint8_t), M_NOWAIT);
+ if (mtag == NULL)
+ return (ENOMEM);
+ m_tag_prepend(m, mtag);
+ }
+
+ *(uint8_t *)(mtag + 1) = prio;
+ return (0);
+}
+
+static int
+pf_match_ieee8021q_pcp(u_int8_t prio, struct mbuf *m)
+{
+ struct m_tag *mtag;
+ u_int8_t mpcp;
+
+ mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_IN, NULL);
+ if (mtag == NULL)
+ return (0);
+
+ if (prio == PF_PRIO_ZERO)
+ prio = 0;
+
+ mpcp = *(uint8_t *)(mtag + 1);
+
+ return (mpcp == prio);
+}
+
static void
pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
struct pf_rule *r)
@@ -3317,6 +3357,9 @@
!pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
pd->lookup.gid))
r = TAILQ_NEXT(r, entries);
+ else if (r->prio &&
+ !pf_match_ieee8021q_pcp(r->prio, m))
+ r = TAILQ_NEXT(r, entries);
else if (r->prob &&
r->prob <= arc4random())
r = TAILQ_NEXT(r, entries);
@@ -3779,6 +3822,9 @@
pd->proto == IPPROTO_ICMPV6) &&
(r->type || r->code))
r = TAILQ_NEXT(r, entries);
+ else if (r->prio &&
+ !pf_match_ieee8021q_pcp(r->prio, m))
+ r = TAILQ_NEXT(r, entries);
else if (r->prob && r->prob <=
(arc4random() % (UINT_MAX - 1) + 1))
r = TAILQ_NEXT(r, entries);
@@ -6003,6 +6049,18 @@
if (r->rtableid >= 0)
M_SETFIB(m, r->rtableid);
+ if (r->scrub_flags & PFSTATE_SETPRIO) {
+ if (pd.tos & IPTOS_LOWDELAY)
+ pqid = 1;
+ if (pf_ieee8021q_setpcp(m, r->set_prio[pqid])) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_MEMORY);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: failed to allocate 802.1q mtag\n"));
+ }
+ }
+
#ifdef ALTQ
if (action == PF_PASS && r->qid) {
if (pd.pf_mtag == NULL &&
@@ -6176,7 +6234,7 @@
struct pf_state *s = NULL;
struct pf_ruleset *ruleset = NULL;
struct pf_pdesc pd;
- int off, terminal = 0, dirndx, rh_cnt = 0;
+ int off, terminal = 0, dirndx, rh_cnt = 0, pqid = 0;
int fwdir = dir;
M_ASSERTPKTHDR(m);
@@ -6449,6 +6507,18 @@
if (r->rtableid >= 0)
M_SETFIB(m, r->rtableid);
+ if (r->scrub_flags & PFSTATE_SETPRIO) {
+ if (pd.tos & IPTOS_LOWDELAY)
+ pqid = 1;
+ if (pf_ieee8021q_setpcp(m, r->set_prio[pqid])) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_MEMORY);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: failed to allocate 802.1q mtag\n"));
+ }
+ }
+
#ifdef ALTQ
if (action == PF_PASS && r->qid) {
if (pd.pf_mtag == NULL &&
Index: head/sys/netpfil/pf/pf_ioctl.c
===================================================================
--- head/sys/netpfil/pf/pf_ioctl.c
+++ head/sys/netpfil/pf/pf_ioctl.c
@@ -1242,6 +1242,10 @@
error = ENOMEM;
if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
error = EINVAL;
+ if (rule->scrub_flags & PFSTATE_SETPRIO &&
+ (rule->set_prio[0] > PF_PRIO_MAX ||
+ rule->set_prio[1] > PF_PRIO_MAX))
+ error = EINVAL;
TAILQ_FOREACH(pa, &V_pf_pabuf, entries)
if (pa->addr.type == PF_ADDR_TABLE) {
pa->addr.p.tbl = pfr_attach_table(ruleset,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 14, 8:08 AM (2 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28692952
Default Alt Text
D6786.diff (11 KB)
Attached To
Mode
D6786: pf: Filter on and set vlan PCP values
Attached
Detach File
Event Timeline
Log In to Comment