QinQ support: implement details - need help!

rozhuk.im at gmail.com rozhuk.im at gmail.com
Fri Oct 14 19:29:35 UTC 2011


...
IEEE 802.1ad (802.1QinQ) specifies architecture and bridge protocols to
provide separate instances of the MAC services to multiple independent users
of a Bridged Local Area Network in a manner that does not require
cooperation among the users, and requires a minimum of cooperation between
the users and the provider of the MAC service.

The idea is to provide, for example, the possibility for customers to run
their own VLANs inside service provider's provided VLAN. This way the
service provider can just configure one VLAN for the customer and customer
can then treat that VLAN as if it was a trunk.
...
http://en.wikipedia.org/wiki/802.1ad



"Customer" VLAN - ether_type: 0x8100
Stored in:
struct pkthdr {
...
	union {
		u_int16_t vt_vtag;	/* Ethernet 802.1p+q vlan tag */
		u_int16_t vt_nrecs;	/* # of IGMPv3 records in this chain
*/
	} PH_vt;
	SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */
};
#define ether_vtag	PH_vt.vt_vtag



"Service Provider" VLAN - ether_type: 0x88a8/0x8100/0x9100
How I can store it in packet?
How to store tag for QinQinQ?






VLAN tags store implementation (IMHO)


Ethernet packet:
| Dst_MAC | Src_MAC | 802.1Q_Tag2 | 802.1Q_Tag1 | 802.1Q_Tag0 |
Ether_type/size | Payload |

802.1Q Tag0 = "Customer" VLAN - ether_type: 0x8100, stored in
pkthdr.PH_vt.vt_vtag (now) (IEEE 802.1Q)
802.1Q Tag1 = "Service Provider" / MetroTag... (IEEE 802.1ad)
802.1Q Tag2 = SomeTag... (QinQinQ)


I found part of old code in /usr/src/sys/dev/mxge/if_mxge.c:
...
	/* save the tag */
#ifdef MXGE_NEW_VLAN_API	
	m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag);
#else
	{
		struct m_tag *mtag;
		mtag = m_tag_alloc(MTAG_VLAN, MTAG_VLAN_TAG, sizeof(u_int),
				   M_NOWAIT);
		if (mtag == NULL)
			return;
		VLAN_TAG_VALUE(mtag) = ntohs(evl->evl_tag);
		m_tag_prepend(m, mtag);
	}

#endif
	m->m_flags |= M_VLANTAG;
...


1. Compact scheme:
#define	MTAG_VLAN_T0	1035328035 /* m_tag_cookie */
#define	MTAG_VLAN_T1	(MTAG_VLAN_T0 + 1)
#define	MTAG_VLAN_T2	(MTAG_VLAN_T1 + 1)
#define	MTAG_VLAN_T3	(MTAG_VLAN_T2 + 1)

Store vt_vtag in m_tag_id
ng_vlan / if_vlan will use for tag/untag one of MTAG_VLAN_Tx m_tag_cookie
and tunable ether_type for vlan encapsulation:
lower <-> ng_vlan(MTAG_VLAN_T0) <-> ng_vlan(MTAG_VLAN_T1) <->
ng_vlan(MTAG_VLAN_T2) <-> upper


2. OpenBSD compatible
#ifdef <OPENBSD>
#define	MTAG_VLAN		MTAG_ABI_COMPAT /* cookie */
#define	MTAG_VLAN_TAG0	1035328035
#else
#define	MTAG_VLAN		1035328035	/* m_tag_cookie */
#define	MTAG_VLAN_TAG0	0		/* tag of VLAN interface */
#endif

#define	MTAG_VLAN_TAG1 (MTAG_VLAN_TAG0 + 1)
#define	MTAG_VLAN_TAG2 (MTAG_VLAN_TAG1 + 1)
#define	MTAG_VLAN_TAG3 (MTAG_VLAN_TAG2 + 1)

struct mv_tag {
	struct m_tag	tag;
	u_int16_t		vt_vtag;	/* Ethernet 802.1p+q vlan
tag */
};

ng_vlan / if_vlan will use for tag/untag one of MTAG_VLAN_TAGx m_tag_id and
tunable ether_type for vlan encapsulation:
lower <-> ng_vlan(MTAG_VLAN_TAG0) <-> ng_vlan(MTAG_VLAN_TAG1) <->
ng_vlan(MTAG_VLAN_TAG2) <-> upper


3. Extended
Same as 2, but

struct mv_tag {
	struct m_tag	tag;
	u_int16_t		vt_vtag;	/* Ethernet 802.1p+q vlan
tag */
	u_int16_t		ether_type;	/* Ethernet type for TAG */
};



Major question is:
were store 802.1Q Tag0 = "Customer" VLAN (ether_type: 0x8100, IEEE 802.1Q):
in pkthdr.PH_vt.vt_vtag or in struct m_tag?


ng_vlan modifications (I can make):
+ tunable ether_type for vlan encapsulation
+ tunable on/off encapsulation (to prevent network adapter encapsulation)
+ tunable m_tag identifier for VLAN tag
...???



Any comments before I start?



PS: Trick:
kern.ipc.max_linkhdr should be increased via sysctl:
20 - 1 VLAN tag (.Q)
24 - 2 VLAN tags (QinQ)
28 - 3 VLAN tags (QinQinQ)
32 - 4 VLAN tags (...)


 
--
Rozhuk Ivan
  





More information about the freebsd-net mailing list