svn commit: r301998 - in head: sbin/pfctl share/man/man5 sys/net sys/netpfil/pf
Marcelo Araujo
araujobsdport at gmail.com
Sat Jun 18 02:28:52 UTC 2016
Thanks to work on it Kristof!
On Jun 18, 2016 2:22 AM, "Kristof Provost" <kp at freebsd.org> wrote:
> Author: kp
> Date: Fri Jun 17 18:21:55 2016
> New Revision: 301998
> URL: https://svnweb.freebsd.org/changeset/base/301998
>
> Log:
> pf: Filter on and set vlan PCP values
>
> Adopt the OpenBSD syntax for setting and filtering on VLAN PCP values.
> This
> introduces two new keywords: 'set prio' to set the PCP value, and 'prio'
> to
> filter on it.
>
> Reviewed by: allanjude, araujo
> Approved by: re (gjb)
> Obtained from: OpenBSD (mostly)
> Differential Revision: https://reviews.freebsd.org/D6786
>
> Modified:
> head/sbin/pfctl/parse.y
> head/sbin/pfctl/pfctl_parser.c
> head/share/man/man5/pf.conf.5
> head/sys/net/pfvar.h
> head/sys/netpfil/pf/pf.c
> head/sys/netpfil/pf/pf_ioctl.c
>
> Modified: head/sbin/pfctl/parse.y
>
> ==============================================================================
> --- head/sbin/pfctl/parse.y Fri Jun 17 17:34:28 2016 (r301997)
> +++ head/sbin/pfctl/parse.y Fri Jun 17 18:21:55 2016 (r301998)
> @@ -217,6 +217,8 @@ struct filter_opts {
> #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 @@ struct filter_opts {
> 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 @@ int parseport(char *, struct range *r, i
> %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 @@ int parseport(char *, struct range *r, i
> %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 @@ int parseport(char *, struct range *r, i
> %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 @@ anchorrule : ANCHOR anchorname dir quick
> 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 @@ pfrule : action dir logquick interface
> 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_opt : USER uids {
> 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_opt : USER uids {
> 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 @@ lookup(char *s)
> { "overload", OVERLOAD},
> { "pass", PASS},
> { "port", PORT},
> + { "prio", PRIO},
> { "priority", PRIORITY},
> { "priq", PRIQ},
> { "probability", PROBABILITY},
>
> Modified: head/sbin/pfctl/pfctl_parser.c
>
> ==============================================================================
> --- head/sbin/pfctl/pfctl_parser.c Fri Jun 17 17:34:28 2016
> (r301997)
> +++ head/sbin/pfctl/pfctl_parser.c Fri Jun 17 18:21:55 2016
> (r301998)
> @@ -841,6 +841,21 @@ print_rule(struct pf_rule *r, const char
> }
> 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)
>
> Modified: head/share/man/man5/pf.conf.5
>
> ==============================================================================
> --- head/share/man/man5/pf.conf.5 Fri Jun 17 17:34:28 2016
> (r301997)
> +++ head/share/man/man5/pf.conf.5 Fri Jun 17 18:21:55 2016
> (r301998)
> @@ -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 @@ For example:
> 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 @@ For example, the following rule will dro
> .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 @@ filteropt = user | group | flags |
> "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 ]
>
> Modified: head/sys/net/pfvar.h
>
> ==============================================================================
> --- head/sys/net/pfvar.h Fri Jun 17 17:34:28 2016 (r301997)
> +++ head/sys/net/pfvar.h Fri Jun 17 18:21:55 2016 (r301998)
> @@ -540,7 +540,7 @@ struct pf_rule {
> 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 @@ struct pf_rule {
> #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 @@ struct pf_state {
> /* 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 */
>
>
> Modified: head/sys/netpfil/pf/pf.c
>
> ==============================================================================
> --- head/sys/netpfil/pf/pf.c Fri Jun 17 17:34:28 2016 (r301997)
> +++ head/sys/netpfil/pf/pf.c Fri Jun 17 18:21:55 2016 (r301998)
> @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
> #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_tcp(struct mbuf *replyto, const
> 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_test_rule(struct pf_rule **rm, struct
> !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 @@ pf_test_fragment(struct pf_rule **rm, in
> 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 @@ done:
> 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 @@ pf_test6(int dir, struct ifnet *ifp, str
> 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 @@ done:
> 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 &&
>
> Modified: head/sys/netpfil/pf/pf_ioctl.c
>
> ==============================================================================
> --- head/sys/netpfil/pf/pf_ioctl.c Fri Jun 17 17:34:28 2016
> (r301997)
> +++ head/sys/netpfil/pf/pf_ioctl.c Fri Jun 17 18:21:55 2016
> (r301998)
> @@ -1242,6 +1242,10 @@ pfioctl(struct cdev *dev, u_long cmd, ca
> 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,
> _______________________________________________
> svn-src-head at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-head
> To unsubscribe, send any mail to "svn-src-head-unsubscribe at freebsd.org"
>
More information about the svn-src-head
mailing list