Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 Jun 2016 19:54:31 +0300
From:      Slawa Olhovchenkov <slw@zxy.spb.ru>
To:        Marcelo Araujo <araujo@FreeBSD.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r301496 - in head: sbin/ifconfig share/man/man4 sys/net sys/sys
Message-ID:  <20160606165431.GF75625@zxy.spb.ru>
In-Reply-To: <201606060951.u569pwOI063390@repo.freebsd.org>
References:  <201606060951.u569pwOI063390@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Jun 06, 2016 at 09:51:58AM +0000, Marcelo Araujo wrote:

> Author: araujo
> Date: Mon Jun  6 09:51:58 2016
> New Revision: 301496
> URL: https://svnweb.freebsd.org/changeset/base/301496
> 
> Log:
>   Add support to priority code point (PCP) that is an 3-bit field
>   which refers to IEEE 802.1p class of service and maps to the frame
>   priority level.
>   
>   Values in order of priority are: 1 (Background (lowest)),
>   0 (Best effort (default)), 2 (Excellent effort),
>   3 (Critical applications), 4 (Video, < 100ms latency),
>   5 (Video, < 10ms latency), 6 (Internetwork control) and
>   7 (Network control (highest)).

What purpose to use 4 for video?
http://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus1000/sw/4_0/qos/configuration/guide/nexus1000v_qos/qos_6dscp_val.pdf
point video is 3.

>   Example of usage:
>   root# ifconfig em0.1 create
>   root# ifconfig em0.1 vlanpcp 3
>   
>   Note:
>   The review D801 includes the pf(4) part, but as discussed with kristof,
>   we won't commit the pf(4) bits for now.
>   The credits of the original code is from rwatson.
>   
>   Differential Revision:	https://reviews.freebsd.org/D801
>   Reviewed by:	gnn, adrian, loos
>   Discussed with: rwatson, glebius, kristof
>   Tested by:	many including Matthew Grooms <mgrooms__shrew.net>
>   Obtained from:	pfSense
>   Relnotes:	Yes
> 
> Modified:
>   head/sbin/ifconfig/ifconfig.8
>   head/sbin/ifconfig/ifvlan.c
>   head/share/man/man4/vlan.4
>   head/sys/net/if.h
>   head/sys/net/if_vlan.c
>   head/sys/net/if_vlan_var.h
>   head/sys/sys/priv.h
> 
> Modified: head/sbin/ifconfig/ifconfig.8
> ==============================================================================
> --- head/sbin/ifconfig/ifconfig.8	Mon Jun  6 09:30:31 2016	(r301495)
> +++ head/sbin/ifconfig/ifconfig.8	Mon Jun  6 09:51:58 2016	(r301496)
> @@ -2614,6 +2614,29 @@ Note that
>  and
>  .Cm vlandev
>  must both be set at the same time.
> +.It Cm vlanpcp Ar priority_code_point
> +Priority code point 
> +.Pq Dv PCP
> +is an 3-bit field which refers to the IEEE 802.1p
> +class of service and maps to the frame priority level.
> +.Pp
> +Values in order of priority are:
> +.Cm 1 
> +.Pq Dv Background (lowest) ,
> +.Cm 0
> +.Pq Dv Best effort (default) ,
> +.Cm 2
> +.Pq Dv Excellent effort ,
> +.Cm 3
> +.Pq Dv Critical applications ,
> +.Cm 4
> +.Pq Dv Video, < 100ms latency ,
> +.Cm 5
> +.Pq Dv Video, < 10ms latency ,
> +.Cm 6
> +.Pq Dv Internetwork control ,
> +.Cm 7
> +.Pq Dv Network control (highest) .
>  .It Cm vlandev Ar iface
>  Associate the physical interface
>  .Ar iface
> 
> Modified: head/sbin/ifconfig/ifvlan.c
> ==============================================================================
> --- head/sbin/ifconfig/ifvlan.c	Mon Jun  6 09:30:31 2016	(r301495)
> +++ head/sbin/ifconfig/ifvlan.c	Mon Jun  6 09:51:58 2016	(r301496)
> @@ -1,6 +1,10 @@
>  /*
> - * Copyright (c) 1999
> - *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
> + * Copyright (c) 1999 Bill Paul <wpaul@ctr.columbia.edu>
> + * Copyright (c) 2012 ADARA Networks, Inc.
> + * All rights reserved.
> +  *
> + * Portions of this software were developed by Robert N. M. Watson under
> + * contract to ADARA Networks, Inc.
>   *
>   * Redistribution and use in source and binary forms, with or without
>   * modification, are permitted provided that the following conditions
> @@ -78,10 +82,14 @@ vlan_status(int s)
>  {
>  	struct vlanreq		vreq;
>  
> -	if (getvlan(s, &ifr, &vreq) != -1)
> -		printf("\tvlan: %d parent interface: %s\n",
> -		    vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
> -		    "<none>" : vreq.vlr_parent);
> +	if (getvlan(s, &ifr, &vreq) == -1)
> +		return;
> +	printf("\tvlan: %d", vreq.vlr_tag);
> +	if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1)
> +		printf(" vlanpcp: %u", ifr.ifr_vlan_pcp);
> +	printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ?
> +	    "<none>" : vreq.vlr_parent);
> +	printf("\n");
>  }
>  
>  static void
> @@ -149,6 +157,22 @@ DECL_CMD_FUNC(setvlandev, val, d)
>  }
>  
>  static
> +DECL_CMD_FUNC(setvlanpcp, val, d)
> +{
> +	u_long ul;
> +	char *endp;
> +
> +	ul = strtoul(val, &endp, 0);
> +	if (*endp != '\0')
> +		errx(1, "invalid value for vlanpcp");
> +	if (ul > 7)
> +		errx(1, "value for vlanpcp out of range");
> +	ifr.ifr_vlan_pcp = ul;
> +	if (ioctl(s, SIOCSVLANPCP, (caddr_t)&ifr) == -1)
> +		err(1, "SIOCSVLANPCP");
> +}
> +
> +static
>  DECL_CMD_FUNC(unsetvlandev, val, d)
>  {
>  	struct vlanreq		vreq;
> @@ -169,6 +193,7 @@ DECL_CMD_FUNC(unsetvlandev, val, d)
>  static struct cmd vlan_cmds[] = {
>  	DEF_CLONE_CMD_ARG("vlan",			setvlantag),
>  	DEF_CLONE_CMD_ARG("vlandev",			setvlandev),
> +	DEF_CMD_ARG("vlanpcp",				setvlanpcp),
>  	/* NB: non-clone cmds */
>  	DEF_CMD_ARG("vlan",				setvlantag),
>  	DEF_CMD_ARG("vlandev",				setvlandev),
> 
> Modified: head/share/man/man4/vlan.4
> ==============================================================================
> --- head/share/man/man4/vlan.4	Mon Jun  6 09:30:31 2016	(r301495)
> +++ head/share/man/man4/vlan.4	Mon Jun  6 09:51:58 2016	(r301496)
> @@ -203,5 +203,3 @@ can be corrected manually if used in con
>  .Sh SEE ALSO
>  .Xr ifconfig 8 ,
>  .Xr sysctl 8
> -.Sh BUGS
> -No 802.1Q features except VLAN tagging are implemented.
> 
> Modified: head/sys/net/if.h
> ==============================================================================
> --- head/sys/net/if.h	Mon Jun  6 09:30:31 2016	(r301495)
> +++ head/sys/net/if.h	Mon Jun  6 09:51:58 2016	(r301496)
> @@ -393,6 +393,7 @@ struct	ifreq {
>  		caddr_t	ifru_data;
>  		int	ifru_cap[2];
>  		u_int	ifru_fib;
> +		u_char	ifru_vlan_pcp;
>  	} ifr_ifru;
>  #define	ifr_addr	ifr_ifru.ifru_addr	/* address */
>  #define	ifr_dstaddr	ifr_ifru.ifru_dstaddr	/* other end of p-to-p link */
> @@ -410,6 +411,7 @@ struct	ifreq {
>  #define	ifr_curcap	ifr_ifru.ifru_cap[1]	/* current capabilities */
>  #define	ifr_index	ifr_ifru.ifru_index	/* interface index */
>  #define	ifr_fib		ifr_ifru.ifru_fib	/* interface fib */
> +#define	ifr_vlan_pcp	ifr_ifru.ifru_vlan_pcp	/* VLAN priority */
>  };
>  
>  #define	_SIZEOF_ADDR_IFREQ(ifr) \
> 
> Modified: head/sys/net/if_vlan.c
> ==============================================================================
> --- head/sys/net/if_vlan.c	Mon Jun  6 09:30:31 2016	(r301495)
> +++ head/sys/net/if_vlan.c	Mon Jun  6 09:51:58 2016	(r301496)
> @@ -1,5 +1,9 @@
>  /*-
>   * Copyright 1998 Massachusetts Institute of Technology
> + * Copyright 2012 ADARA Networks, Inc.
> + *
> + * Portions of this software were developed by Robert N. M. Watson under
> + * contract to ADARA Networks, Inc.
>   *
>   * Permission to use, copy, modify, and distribute this software and
>   * its documentation for any purpose and without fee is hereby
> @@ -29,8 +33,7 @@
>  
>  /*
>   * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
> - * Might be extended some day to also handle IEEE 802.1p priority
> - * tagging.  This is sort of sneaky in the implementation, since
> + * This is sort of sneaky in the implementation, since
>   * we need to pretend to be enough of an Ethernet implementation
>   * to make arp work.  The way we do this is by telling everyone
>   * that we are an Ethernet, and then catch the packets that
> @@ -52,6 +55,7 @@ __FBSDID("$FreeBSD$");
>  #include <sys/mbuf.h>
>  #include <sys/module.h>
>  #include <sys/rmlock.h>
> +#include <sys/priv.h>
>  #include <sys/queue.h>
>  #include <sys/socket.h>
>  #include <sys/sockio.h>
> @@ -114,6 +118,8 @@ struct	ifvlan {
>  		int	ifvm_mintu;	/* min transmission unit */
>  		uint16_t ifvm_proto;	/* encapsulation ethertype */
>  		uint16_t ifvm_tag;	/* tag to apply on packets leaving if */
> +              	uint16_t ifvm_vid;	/* VLAN ID */
> +		uint8_t	ifvm_pcp;	/* Priority Code Point (PCP). */
>  	}	ifv_mib;
>  	SLIST_HEAD(, vlan_mc_entry) vlan_mc_listhead;
>  #ifndef VLAN_ARRAY
> @@ -121,7 +127,9 @@ struct	ifvlan {
>  #endif
>  };
>  #define	ifv_proto	ifv_mib.ifvm_proto
> -#define	ifv_vid		ifv_mib.ifvm_tag
> +#define	ifv_tag		ifv_mib.ifvm_tag
> +#define	ifv_vid 	ifv_mib.ifvm_vid
> +#define	ifv_pcp		ifv_mib.ifvm_pcp
>  #define	ifv_encaplen	ifv_mib.ifvm_encaplen
>  #define	ifv_mtufudge	ifv_mib.ifvm_mtufudge
>  #define	ifv_mintu	ifv_mib.ifvm_mintu
> @@ -147,6 +155,15 @@ static VNET_DEFINE(int, soft_pad);
>  SYSCTL_INT(_net_link_vlan, OID_AUTO, soft_pad, CTLFLAG_RW | CTLFLAG_VNET,
>      &VNET_NAME(soft_pad), 0, "pad short frames before tagging");
>  
> +/*
> + * For now, make preserving PCP via an mbuf tag optional, as it increases
> + * per-packet memory allocations and frees.  In the future, it would be
> + * preferable to reuse ether_vtag for this, or similar.
> + */
> +static int vlan_mtag_pcp = 0;
> +SYSCTL_INT(_net_link_vlan, OID_AUTO, mtag_pcp, CTLFLAG_RW, &vlan_mtag_pcp, 0,
> +	"Retain VLAN PCP information as packets are passed up the stack");
> +
>  static const char vlanname[] = "vlan";
>  static MALLOC_DEFINE(M_VLAN, vlanname, "802.1Q Virtual LAN Interface");
>  
> @@ -697,6 +714,16 @@ vlan_devat(struct ifnet *ifp, uint16_t v
>  }
>  
>  /*
> + * Recalculate the cached VLAN tag exposed via the MIB.
> + */
> +static void
> +vlan_tag_recalculate(struct ifvlan *ifv)
> +{
> +
> +       ifv->ifv_tag = EVL_MAKETAG(ifv->ifv_vid, ifv->ifv_pcp, 0);
> +}
> +
> +/*
>   * VLAN support can be loaded as a module.  The only place in the
>   * system that's intimately aware of this is ether_input.  We hook
>   * into this code through vlan_input_p which is defined there and
> @@ -1009,6 +1036,8 @@ vlan_transmit(struct ifnet *ifp, struct 
>  {
>  	struct ifvlan *ifv;
>  	struct ifnet *p;
> +	struct m_tag *mtag;
> +	uint16_t tag;
>  	int error, len, mcast;
>  
>  	ifv = ifp->if_softc;
> @@ -1064,11 +1093,16 @@ vlan_transmit(struct ifnet *ifp, struct 
>  	 * knows how to find the VLAN tag to use, so we attach a
>  	 * packet tag that holds it.
>  	 */
> +	if (vlan_mtag_pcp && (mtag = m_tag_locate(m, MTAG_8021Q,
> +	    MTAG_8021Q_PCP_OUT, NULL)) != NULL)
> +		tag = EVL_MAKETAG(ifv->ifv_vid, *(uint8_t *)(mtag + 1), 0);
> +	else
> +              tag = ifv->ifv_tag;
>  	if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
> -		m->m_pkthdr.ether_vtag = ifv->ifv_vid;
> +		m->m_pkthdr.ether_vtag = tag;
>  		m->m_flags |= M_VLANTAG;
>  	} else {
> -		m = ether_vlanencap(m, ifv->ifv_vid);
> +		m = ether_vlanencap(m, tag);
>  		if (m == NULL) {
>  			if_printf(ifp, "unable to prepend VLAN header\n");
>  			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
> @@ -1103,7 +1137,8 @@ vlan_input(struct ifnet *ifp, struct mbu
>  	struct ifvlantrunk *trunk = ifp->if_vlantrunk;
>  	struct ifvlan *ifv;
>  	TRUNK_LOCK_READER;
> -	uint16_t vid;
> +	struct m_tag *mtag;
> +	uint16_t vid, tag;
>  
>  	KASSERT(trunk != NULL, ("%s: no trunk", __func__));
>  
> @@ -1112,7 +1147,7 @@ vlan_input(struct ifnet *ifp, struct mbu
>  		 * Packet is tagged, but m contains a normal
>  		 * Ethernet frame; the tag is stored out-of-band.
>  		 */
> -		vid = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
> +		tag = m->m_pkthdr.ether_vtag;
>  		m->m_flags &= ~M_VLANTAG;
>  	} else {
>  		struct ether_vlan_header *evl;
> @@ -1128,7 +1163,7 @@ vlan_input(struct ifnet *ifp, struct mbu
>  				return;
>  			}
>  			evl = mtod(m, struct ether_vlan_header *);
> -			vid = EVL_VLANOFTAG(ntohs(evl->evl_tag));
> +			tag = ntohs(evl->evl_tag);
>  
>  			/*
>  			 * Remove the 802.1q header by copying the Ethernet
> @@ -1152,6 +1187,8 @@ vlan_input(struct ifnet *ifp, struct mbu
>  		}
>  	}
>  
> +	vid = EVL_VLANOFTAG(tag);
> +
>  	TRUNK_RLOCK(trunk);
>  	ifv = vlan_gethash(trunk, vid);
>  	if (ifv == NULL || !UP_AND_RUNNING(ifv->ifv_ifp)) {
> @@ -1162,6 +1199,28 @@ vlan_input(struct ifnet *ifp, struct mbu
>  	}
>  	TRUNK_RUNLOCK(trunk);
>  
> +	if (vlan_mtag_pcp) {
> +		/*
> +		 * While uncommon, it is possible that we will find a 802.1q
> +		 * packet encapsulated inside another packet that also had an
> +		 * 802.1q header.  For example, ethernet tunneled over IPSEC
> +		 * arriving over ethernet.  In that case, we replace the
> +		 * existing 802.1q PCP m_tag value.
> +		 */
> +		mtag = m_tag_locate(m, MTAG_8021Q, MTAG_8021Q_PCP_IN, NULL);
> +		if (mtag == NULL) {
> +			mtag = m_tag_alloc(MTAG_8021Q, MTAG_8021Q_PCP_IN,
> +			    sizeof(uint8_t), M_NOWAIT);
> +			if (mtag == NULL) {
> +				m_freem(m);
> +				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
> +				return;
> +			}
> +			m_tag_prepend(m, mtag);
> +		}
> +		*(uint8_t *)(mtag + 1) = EVL_PRIOFTAG(tag);
> +	}
> +
>  	m->m_pkthdr.rcvif = ifv->ifv_ifp;
>  	if_inc_counter(ifv->ifv_ifp, IFCOUNTER_IPACKETS, 1);
>  
> @@ -1201,7 +1260,7 @@ vlan_config(struct ifvlan *ifv, struct i
>  		vlan_inithash(trunk);
>  		VLAN_LOCK();
>  		if (p->if_vlantrunk != NULL) {
> -			/* A race that that is very unlikely to be hit. */
> +			/* A race that is very unlikely to be hit. */
>  			vlan_freehash(trunk);
>  			free(trunk, M_VLAN);
>  			goto exists;
> @@ -1218,6 +1277,8 @@ exists:
>  	}
>  
>  	ifv->ifv_vid = vid;	/* must set this before vlan_inshash() */
> +	ifv->ifv_pcp = 0;       /* Default: best effort delivery. */
> +	vlan_tag_recalculate(ifv);
>  	error = vlan_inshash(trunk, ifv);
>  	if (error)
>  		goto done;
> @@ -1705,6 +1766,34 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd
>  		}
>  		break;
>  
> +	case SIOCGVLANPCP:
> +#ifdef VIMAGE
> +		if (ifp->if_vnet != ifp->if_home_vnet) {
> +			error = EPERM;
> +			break;
> +		}
> +#endif
> +		ifr->ifr_vlan_pcp = ifv->ifv_pcp;
> +		break;
> +
> +	case SIOCSVLANPCP:
> +#ifdef VIMAGE
> +		if (ifp->if_vnet != ifp->if_home_vnet) {
> +			error = EPERM;
> +			break;
> +		}
> +#endif
> +		error = priv_check(curthread, PRIV_NET_SETVLANPCP);
> +		if (error)
> +			break;
> +		if (ifr->ifr_vlan_pcp > 7) {
> +			error = EINVAL;
> +			break;
> +		}
> +		ifv->ifv_pcp = ifr->ifr_vlan_pcp;
> +		vlan_tag_recalculate(ifv);
> +		break;
> +
>  	default:
>  		error = EINVAL;
>  		break;
> 
> Modified: head/sys/net/if_vlan_var.h
> ==============================================================================
> --- head/sys/net/if_vlan_var.h	Mon Jun  6 09:30:31 2016	(r301495)
> +++ head/sys/net/if_vlan_var.h	Mon Jun  6 09:51:58 2016	(r301496)
> @@ -73,6 +73,23 @@ struct	vlanreq {
>  #define	SIOCSETVLAN	SIOCSIFGENERIC
>  #define	SIOCGETVLAN	SIOCGIFGENERIC
>  
> +#define	SIOCGVLANPCP	_IOWR('i', 152, struct ifreq)	/* Get VLAN PCP */
> +#define	SIOCSVLANPCP	 _IOW('i', 153, struct ifreq)	/* Set VLAN PCP */
> +
> +/*
> + * Names for 802.1q priorities ("802.1p").  Notice that in this scheme,
> + * (0 < 1), allowing default 0-tagged traffic to take priority over background
> + * tagged traffic.
> + */
> +#define	IEEE8021Q_PCP_BK	1	/* Background (lowest) */
> +#define	IEEE8021Q_PCP_BE	0	/* Best effort (default) */
> +#define	IEEE8021Q_PCP_EE	2	/* Excellent effort */
> +#define	IEEE8021Q_PCP_CA	3	/* Critical applications */
> +#define	IEEE8021Q_PCP_VI	4	/* Video, < 100ms latency */
> +#define	IEEE8021Q_PCP_VO	5	/* Video, < 10ms latency */
> +#define	IEEE8021Q_PCP_IC	6	/* Internetwork control */
> +#define	IEEE8021Q_PCP_NC	7	/* Network control (highest) */
> +
>  #ifdef _KERNEL
>  /*
>   * Drivers that are capable of adding and removing the VLAN header
> @@ -110,6 +127,16 @@ struct	vlanreq {
>   * if_capabilities.
>   */
>  
> +/*
> + * The 802.1q code may also tag mbufs with the PCP (priority) field for use in
> + * other layers of the stack, in which case an m_tag will be used.  This is
> + * semantically quite different from use of the ether_vtag field, which is
> + * defined only between the device driver and VLAN layer.
> + */
> +#define	MTAG_8021Q		1326104895
> +#define	MTAG_8021Q_PCP_IN	0		/* Input priority. */
> +#define	MTAG_8021Q_PCP_OUT	1		/* Output priority. */
> +
>  #define	VLAN_CAPABILITIES(_ifp) do {				\
>  	if ((_ifp)->if_vlantrunk != NULL) 			\
>  		(*vlan_trunk_cap_p)(_ifp);			\
> 
> Modified: head/sys/sys/priv.h
> ==============================================================================
> --- head/sys/sys/priv.h	Mon Jun  6 09:30:31 2016	(r301495)
> +++ head/sys/sys/priv.h	Mon Jun  6 09:51:58 2016	(r301496)
> @@ -342,6 +342,7 @@
>  #define	PRIV_NET_SETIFDESCR	418	/* Set interface description. */
>  #define	PRIV_NET_SETIFFIB	419	/* Set interface fib. */
>  #define	PRIV_NET_VXLAN		420	/* Administer vxlan. */
> +#define	PRIV_NET_SETVLANPCP	421	/* Set VLAN priority. */
>  
>  /*
>   * 802.11-related privileges.
> _______________________________________________
> svn-src-all@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160606165431.GF75625>