Skip to contentSkip to conversation

VLAN-tagging

PATCH Superseded Fabian Knittel 2 participants 2 messages Apr 5, 2010 – Apr 8, 2010

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 VLAN-tagging

Hi,

I didn't have much time the last few days, but as I'll be without Internet access Tuesday through Friday I wanted to push out what I've come up with so far. I've attached the diff between my first patch-series and this posting. If people would prefer to see the individual patches in their reworked form, just say so and I'll post those in the future. For now, they're available on the feat_vlan/r12 tag at

git://fsmi-dev.fsmi.uni-karlsruhe.de/openvpn.git

or
http://opensource.fsmi.uni-karlsruhe.de/cgi-bin/gitweb.cgi?p=openvpn.git

The changes:

* Fixed the valid VID range to be from 1-0xFFFE to 1-4094 (0xFFE). Changed the VID field mask to 0x0FFF. (If someone can explain a use-case for VID=0 to me, I might allow that too.)

* "--vlan-tag" was renamed to "--vlan-pvid" and is now also valid in global context (where it configures the PVID for the tap device).

* The boolean "--vlan-tagging" option was replaced by "--vlan-accept raw | tagged | untagged | all". "raw" corresponds to the old "no --vlan-tagging" and "tagged" corresponds to the old "--vlan-tagging". "untagged" accepts only untagged (or priority tagged) packets on the tap device. It assumes they belong to the VID set by the global "--vlan-pvid". "all" accepts VLAN-tagged and untagged packets and handles them the way the "tagged" and "untagged" modes would.

I'm planning to reintroduce the previous on/off switch and just supplement that with the new "--vlan-accept mode" (which would then only allow you to choose between 'tagged | untagged | all'. The thinking behind the two separate switches would be, that "raw" mode makes OpenVPN behave different on a global level, while "tagged", "untagged" and "all" only change the behaviour regarding the tap device. (In theory, "--vlan-accept" could be made into an instance option, allowing clients to send tagged packets, etc..)

* Compile-time switch ("--disable-vlan-tagging" / "--enable-vlan-tagging") to enable/disable the VLAN-tagging feature Default is enabled. When disabled, OpenVPN should behave the same way as in "--vlan-accept raw" mode.

* Added a first attempt at documentation to openvpn.8

* VLAN-tagged packets coming in via the client links are dropped if "--vlan-accept" is in non-"raw" mode. (Priority-tagged packets aren't affected.)

* VLAN-tagged packets coming in through tap, that contain priority information have their priority information preserved and get sent on as priority-tagged packets. I'm not sure whether this is a good idea though. The decision is based on whether the PCP-field is non-zero. I haven't been able to find out what the standard has to say on the matter or what switches typically do in that situation.

Linux allows you to do fixed egress and ingress priority tagging (or more precise: mapping from the TOS field), so that would imply changing the IP-header's TOS field.

Again, the patches have only received light testing so far. I've tested all accept modes though, so there hopefully shouldn't be any obvious brown-paper bag bugs. More thorough testing will hopefully start next week.

BTW, I'll add Signed-Off-By-lines as soon as I'm a bit more confident in the patches. (And ... assuming I don't forget adding the flag, like I did this time. :) )

If you haven't had a thorough look at my previous patch-set yet, I strongly suggest you go through my individual patches from my git tree, as they're IMHO easier to understand one by one.

Cheers
Fabian

configure.ac +12 -0
index 116ff7c..b99bc11 100644
@@ -212,6 +212,12 @@ AC_ARG_ENABLE(selinux,
    [SELINUX="yes"]
 )
 
+AC_ARG_ENABLE(vlan-tagging,
+   [  --disable-vlan-tagging  Disable support for VLAN tagging/untagging],
+   [VLAN_TAGGING="$enableval"],
+   [VLAN_TAGGING="yes"]
+)
+
 AC_ARG_WITH(ssl-headers,
    [  --with-ssl-headers=DIR  Crypto/SSL Include files location],
    [CS_HDR_DIR="$withval"]
@@ -886,6 +892,12 @@ if test "$SELINUX" = "yes"; then
    )
 fi
 
+dnl enable --vlan-tagging
+if test "$VLAN_TAGGING" = "yes"; then
+   AC_DEFINE(ENABLE_VLAN_TAGGING, 1, [Enable VLAN tagging/untagging])
+fi
+
+
 TAP_ID="PRODUCT_TAP_ID"
 TAP_WIN32_MIN_MAJOR="PRODUCT_TAP_WIN32_MIN_MAJOR"
 TAP_WIN32_MIN_MINOR="PRODUCT_TAP_WIN32_MIN_MINOR"
errlevel.h +2 -0
index a092d3f..68128b9 100644
@@ -144,6 +144,8 @@
 #define D_PF_DROPPED_BCAST   LOGLEV(7, 71, M_DEBUG)  /* packet filter dropped a broadcast packet */
 #define D_PF_DEBUG           LOGLEV(7, 72, M_DEBUG)  /* packet filter debugging, must also define PF_DEBUG in pf.h */
 
+#define D_VLAN_DEBUG         LOGLEV(7, 72, M_DEBUG)  /* show VLAN tagging/untagging debug info */
+
 #define D_HANDSHAKE_VERBOSE  LOGLEV(8, 70, M_DEBUG)  /* show detailed description of each handshake */
 #define D_TLS_DEBUG_MED      LOGLEV(8, 70, M_DEBUG)  /* limited info from tls_session routines */
 #define D_INTERVAL           LOGLEV(8, 70, M_DEBUG)  /* show interval.h debugging info */
mroute.c +21 -11
index 4aa7bb4..72ef91a 100644
@@ -164,6 +164,21 @@ mroute_extract_addr_ipv4 (struct mroute_addr *src,
   return ret;
 }
 
+static void mroute_copy_ether_to_addr(struct mroute_addr *maddr,
+				      const uint8_t *eth_addr,
+				      int16_t vid)
+{
+  maddr->type = MR_ADDR_ETHER;
+  maddr->netbits = 0;
+  memcpy (maddr->addr, eth_addr, 6);
+#ifdef ENABLE_VLAN_TAGGING
+  maddr->len = 8;
+  memcpy (maddr->addr + 6, &vid, 2);
+#else
+  maddr->len = 6;
+#endif
+}
+
 unsigned int
 mroute_extract_addr_ether (struct mroute_addr *src,
 			   struct mroute_addr *dest,
@@ -178,19 +193,11 @@ mroute_extract_addr_ether (struct mroute_addr *src,
       const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
       if (src)
 	{
-	  src->type = MR_ADDR_ETHER;
-	  src->netbits = 0;
-	  src->len = 8;
-	  memcpy (src->addr, eth->source, 6);
-	  memcpy (src->addr + 6, &vid, 2);
+          mroute_copy_ether_to_addr(src, eth->source, vid);
 	}
       if (dest)
 	{
-	  dest->type = MR_ADDR_ETHER;
-	  dest->netbits = 0;
-	  dest->len = 8;
-	  memcpy (dest->addr, eth->dest, 6);
-	  memcpy (dest->addr + 6, &vid, 2);
+          mroute_copy_ether_to_addr(dest, eth->dest, vid);
 
 	  /* ethernet broadcast/multicast packet? */
 	  if (is_mac_mcast_addr (eth->dest))
@@ -206,7 +213,8 @@ mroute_extract_addr_ether (struct mroute_addr *src,
 	  if (buf_advance (&b, sizeof (struct openvpn_ethhdr)))
 	    {
 	      uint16_t proto = ntohs (eth->proto);
-	      if (proto == OPENVPN_ETH_P_8021Q)
+	      if (proto == OPENVPN_ETH_P_8021Q &&
+		  BLEN (buf) >= (int) sizeof (struct openvpn_8021qhdr))
 		{
 		  const struct openvpn_8021qhdr *tag = (const struct openvpn_8021qhdr *) BPTR (buf);
 		  proto = ntohs (tag->proto);
@@ -314,7 +322,9 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
 	{
 	case MR_ADDR_ETHER:
 	  buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc)); 
+#ifdef ENABLE_VLAN_TAGGING
 	  buf_printf (&out, "@%d", *(int16_t*)(ma->addr + 6));
+#endif
 	  break;
 	case MR_ADDR_IPV4:
 	  {
multi.c +170 -57

313 lines not on this page · raw message

multi.h +21 -3
index 26b3e1a..3ed1981 100644
@@ -405,7 +405,9 @@ multi_get_timeout (struct multi_context *m, struct timeval *dest)
 static inline bool
 multi_process_outgoing_tun (struct multi_context *m, const unsigned int mpp_flags)
 {
-  void multi_prepend_vlan_identifier (struct multi_instance *mi, struct buffer *buf);
+#ifdef ENABLE_VLAN_TAGGING
+  void multi_prepend_vlan_tag (const struct context *c, struct buffer *buf);
+#endif
   struct multi_instance *mi = m->pending;
   bool ret = true;
 
@@ -416,10 +418,26 @@ multi_process_outgoing_tun (struct multi_context *m, const unsigned int mpp_flag
 	  mi->context.c2.to_tun.len);
 #endif
   set_prefix (mi);
-  if (mi->context.options.vlan_tag)
+#ifdef ENABLE_VLAN_TAGGING
+  if (m->top.options.vlan_accept == VAF_ONLY_UNTAGGED_OR_PRIORITY)
     {
-      multi_prepend_vlan_identifier (mi, &mi->context.c2.to_tun);
+      /* Packets aren't tagged on the tap device. */
+
+      if (m->top.options.vlan_pvid != mi->context.options.vlan_pvid)
+	{
+	  /* Packet is coming from the wrong VID, drop it. */
+	  mi->context.c2.to_tun.len = 0;
+	}
     }
+  else if (m->top.options.vlan_accept == VAF_ONLY_VLAN_TAGGED ||
+	   (m->top.options.vlan_accept == VAF_ALL &&
+	    m->top.options.vlan_pvid != mi->context.options.vlan_pvid))
+    {
+      /* Packets need to be tagged.  Either because all packets are tagged or
+         because the vid matches the port's pvid. */
+      multi_prepend_vlan_tag (&mi->context, &mi->context.c2.to_tun);
+    }
+#endif
   process_outgoing_tun (&mi->context);
   ret = multi_process_post (m, mi, mpp_flags);
   clear_prefix ();
openvpn.8 +81 -0

87 lines not on this page · raw message

options.c +72 -26

167 lines not on this page · raw message

options.h +14 -2
index f4ca502..8d67011 100644
@@ -126,6 +126,16 @@ struct remote_list
 
 #endif
 
+#ifdef ENABLE_VLAN_TAGGING
+enum vlan_acceptable_frames
+{
+  VAF_RAW = 0,
+  VAF_ONLY_VLAN_TAGGED,
+  VAF_ONLY_UNTAGGED_OR_PRIORITY,
+  VAF_ALL,
+};
+#endif
+
 /* Command line options */
 struct options
 {
@@ -510,8 +520,10 @@ struct options
   int route_method;
 #endif
 
-  bool vlan_tagging;
-  int vlan_tag;
+#ifdef ENABLE_VLAN_TAGGING
+  enum vlan_acceptable_frames vlan_accept;
+  int vlan_pvid;
+#endif
 };
 
 #define streq(x, y) (!strcmp((x), (y)))
proto.h +45 -9

85 lines not on this page · raw message

#1 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 68 lines · Fabian Knittel

Hi,

I didn't have much time the last few days, but as I'll be without Internet access Tuesday through Friday I wanted to push out what I've come up with so far. I've attached the diff between my first patch-series and this posting. If people would prefer to see the individual patches in their reworked form, just say so and I'll post those in the future. For now, they're available on the feat_vlan/r12 tag at

git://fsmi-dev.fsmi.uni-karlsruhe.de/openvpn.git

or
http://opensource.fsmi.uni-karlsruhe.de/cgi-bin/gitweb.cgi?p=openvpn.git

The changes:

* Fixed the valid VID range to be from 1-0xFFFE to 1-4094 (0xFFE). Changed the VID field mask to 0x0FFF. (If someone can explain a use-case for VID=0 to me, I might allow that too.)

* "--vlan-tag" was renamed to "--vlan-pvid" and is now also valid in global context (where it configures the PVID for the tap device).

* The boolean "--vlan-tagging" option was replaced by "--vlan-accept raw | tagged | untagged | all". "raw" corresponds to the old "no --vlan-tagging" and "tagged" corresponds to the old "--vlan-tagging". "untagged" accepts only untagged (or priority tagged) packets on the tap device. It assumes they belong to the VID set by the global "--vlan-pvid". "all" accepts VLAN-tagged and untagged packets and handles them the way the "tagged" and "untagged" modes would.

I'm planning to reintroduce the previous on/off switch and just supplement that with the new "--vlan-accept mode" (which would then only allow you to choose between 'tagged | untagged | all'. The thinking behind the two separate switches would be, that "raw" mode makes OpenVPN behave different on a global level, while "tagged", "untagged" and "all" only change the behaviour regarding the tap device. (In theory, "--vlan-accept" could be made into an instance option, allowing clients to send tagged packets, etc..)

* Compile-time switch ("--disable-vlan-tagging" / "--enable-vlan-tagging") to enable/disable the VLAN-tagging feature Default is enabled. When disabled, OpenVPN should behave the same way as in "--vlan-accept raw" mode.

* Added a first attempt at documentation to openvpn.8

* VLAN-tagged packets coming in via the client links are dropped if "--vlan-accept" is in non-"raw" mode. (Priority-tagged packets aren't affected.)

* VLAN-tagged packets coming in through tap, that contain priority information have their priority information preserved and get sent on as priority-tagged packets. I'm not sure whether this is a good idea though. The decision is based on whether the PCP-field is non-zero. I haven't been able to find out what the standard has to say on the matter or what switches typically do in that situation.

Linux allows you to do fixed egress and ingress priority tagging (or more precise: mapping from the TOS field), so that would imply changing the IP-header's TOS field.

Again, the patches have only received light testing so far. I've tested all accept modes though, so there hopefully shouldn't be any obvious brown-paper bag bugs. More thorough testing will hopefully start next week.

Quoted 8 lines

BTW, I'll add Signed-Off-By-lines as soon as I'm a bit more confident in the patches. (And ... assuming I don't forget adding the flag, like I did this time. :) )

If you haven't had a thorough look at my previous patch-set yet, I strongly suggest you go through my individual patches from my git tree, as they're IMHO easier to understand one by one.

I've pulled down your git tree (feat_vlan branch), and published it as feat_vlan_tagging in the openvpn-testing.git tree. Currently it has not been merged into allmerged, before it gets a better review of the latest changes. But I'll pull in changes from your tree on request. Please provide such a summary as above on pull requests, to get more information about what's being pulled in.

kind regards,

David Sommerseth
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAku+LjAACgkQDC186MBRfrr6TgCeJAVtNUUG88PpW9MHoN0D6kSU u88AoJSTDabXdSJz6cr5nT0eJk9uht+M
=81KC
-----END PGP SIGNATURE-----