Remove "VLAN splinters" feature.
authorPravin B Shelar <pshelar@ovn.org>
Mon, 25 Apr 2016 18:27:58 +0000 (11:27 -0700)
committerPravin B Shelar <pshelar@ovn.org>
Wed, 27 Apr 2016 22:00:37 +0000 (15:00 -0700)
The "VLAN splinters" feature works around buggy device drivers in
old Linux versions. But support for the old kernel is dropped, So
now all supported kernel vlan drivers should be working fine with
OVS kernel datapath.
Following patch removes this deprecated feature.

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Acked-by: Ben Pfaff <blp@ovn.org>
19 files changed:
FAQ.md
NEWS
lib/automake.mk
lib/dummy.c
lib/dummy.h
lib/vlandev.c [deleted file]
lib/vlandev.h [deleted file]
ofproto/ofproto-dpif-upcall.c
ofproto/ofproto-dpif-xlate.c
ofproto/ofproto-dpif.c
ofproto/ofproto-dpif.h
ofproto/ofproto-provider.h
ofproto/ofproto.c
ofproto/ofproto.h
tests/automake.mk
tests/testsuite.at
tests/vlan-splinters.at [deleted file]
vswitchd/bridge.c
vswitchd/vswitch.xml

diff --git a/FAQ.md b/FAQ.md
index 16e8a15..28680d6 100644 (file)
--- a/FAQ.md
+++ b/FAQ.md
@@ -1277,7 +1277,7 @@ A: Many drivers in Linux kernels before version 3.3 had VLAN-related
 
    - Use a NIC whose driver does not have VLAN problems.
 
-   - Use "VLAN splinters", a feature in Open vSwitch 1.4 and later
+   - Use "VLAN splinters", a feature in Open vSwitch 1.4 upto 2.5
      that works around bugs in kernel drivers.  To enable VLAN
      splinters on interface eth0, use the command:
 
diff --git a/NEWS b/NEWS
index ea7f3a1..3167e8d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -43,6 +43,7 @@ Post-v2.5.0
      * Introduced SELinux policy package.
    - Datapath Linux kernel compatibility.
      * Dropped support for kernel older than 3.10.
+     * Removed VLAN splinters feature.
    - Tunnels:
      * Flow based tunnel match and action can be used for IPv6 address using
        tun_ipv6_src, tun_ipv6_dst fields.
index 1ec2115..76dfc07 100644 (file)
@@ -267,8 +267,6 @@ lib_libopenvswitch_la_SOURCES = \
        lib/vconn.c \
        lib/vlan-bitmap.c \
        lib/vlan-bitmap.h \
-       lib/vlandev.c \
-       lib/vlandev.h \
        lib/vlog.c \
        lib/lldp/aa-structs.h \
        lib/lldp/lldp.c \
index 5caceee..899a2c0 100644 (file)
@@ -45,7 +45,6 @@ dummy_enable(const char *arg)
     netdev_dummy_register(level);
     dpif_dummy_register(level);
     timeval_dummy_register();
-    vlandev_dummy_enable();
     ofpact_dummy_enable();
 }
 
index 5b8a841..b16ce0b 100644 (file)
@@ -37,7 +37,6 @@ void dummy_enable(const char *arg);
 void dpif_dummy_register(enum dummy_level);
 void netdev_dummy_register(enum dummy_level);
 void timeval_dummy_register(void);
-void vlandev_dummy_enable(void);
 void ofpact_dummy_enable(void);
 
 #endif /* dummy.h */
diff --git a/lib/vlandev.c b/lib/vlandev.c
deleted file mode 100644 (file)
index d2a3191..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (c) 2011, 2013, 2014 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-
-#include "vlandev.h"
-
-#include <errno.h>
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-
-#include "dummy.h"
-#include "hash.h"
-#include "shash.h"
-#include "socket-util.h"
-#include "openvswitch/vlog.h"
-
-VLOG_DEFINE_THIS_MODULE(vlandev);
-
-/* A vlandev implementation. */
-struct vlandev_class {
-    int (*vd_refresh)(void);
-    int (*vd_add)(const char *real_dev, int vid);
-    int (*vd_del)(const char *vlan_dev);
-};
-
-#ifdef __linux__
-static const struct vlandev_class vlandev_linux_class;
-#endif
-static const struct vlandev_class vlandev_stub_class;
-static const struct vlandev_class vlandev_dummy_class;
-
-/* The in-use vlandev implementation. */
-static const struct vlandev_class *vd_class;
-
-/* Maps from a VLAN device name (e.g. "eth0.10") to struct vlan_dev. */
-static struct shash vlan_devs = SHASH_INITIALIZER(&vlan_devs);
-
-/* Maps from a VLAN real device name (e.g. "eth0") to struct vlan_real_dev. */
-static struct shash vlan_real_devs = SHASH_INITIALIZER(&vlan_real_devs);
-
-static int vlandev_add__(const char *vlan_dev, const char *real_dev, int vid);
-static int vlandev_del__(const char *vlan_dev);
-static void vlandev_clear__(void);
-
-static const struct vlandev_class *
-vlandev_get_class(void)
-{
-    if (!vd_class) {
-#if __linux__
-        vd_class = &vlandev_linux_class;
-#else
-        vd_class = &vlandev_stub_class;
-#endif
-    }
-    return vd_class;
-}
-
-/* On Linux, the default implementation of VLAN devices creates and destroys
- * Linux VLAN devices.  On other OSess, the default implementation is a
- * nonfunctional stub.  In either case, this function replaces this default
- * implementation by a "dummy" implementation that simply reports back whatever
- * the client sets up with vlandev_add() and vlandev_del().
- *
- * Don't call this function directly; use dummy_enable() from dummy.h. */
-void
-vlandev_dummy_enable(void)
-{
-    if (vd_class != &vlandev_dummy_class) {
-        vd_class = &vlandev_dummy_class;
-        vlandev_clear__();
-    }
-}
-
-/* Creates a new VLAN device for VLAN 'vid' on top of real Ethernet device
- * 'real_dev'.  Returns 0 if successful, otherwise a positive errno value.  On
- * OSes other than Linux, in the absence of dummies (see
- * vlandev_dummy_enable()), this always fails.
- *
- * The name of the new VLAN device is not easily predictable, because Linux
- * provides multiple naming schemes, does not allow the client to specify a
- * name, and does not directly report the new VLAN device's name.  Use
- * vlandev_refresh() then vlandev_get_name() to find out the new VLAN device's
- * name,. */
-int
-vlandev_add(const char *real_dev, int vid)
-{
-    return vlandev_get_class()->vd_add(real_dev, vid);
-}
-
-/* Deletes the VLAN device named 'vlan_dev'.  Returns 0 if successful,
- * otherwise a positive errno value.  On OSes other than Linux, in the absence
- * of dummies (see vlandev_dummy_enable()), this always fails. */
-int
-vlandev_del(const char *vlan_dev)
-{
-    return vlandev_get_class()->vd_del(vlan_dev);
-}
-
-/* Refreshes the cache of real device to VLAN device mappings reported by
- * vlandev_get_real_devs() and vlandev_get_name().  Without calling this
- * function, changes made by vlandev_add() and vlandev_del() may not be
- * reflected by vlandev_get_real_devs() and vlandev_get_name() output. */
-int
-vlandev_refresh(void)
-{
-    const struct vlandev_class *class = vlandev_get_class();
-    return class->vd_refresh ? class->vd_refresh() : 0;
-}
-
-/* Returns a shash mapping from the name of real Ethernet devices used as the
- * basis of VLAN devices to struct vlan_real_devs.  The caller must not modify
- * or free anything in the returned shash.
- *
- * Changes made by vlandev_add() and vlandev_del() may not be reflected in this
- * function's output without an intervening call to vlandev_refresh(). */
-struct shash *
-vlandev_get_real_devs(void)
-{
-    return &vlan_real_devs;
-}
-
-/* Returns the name of the VLAN device for VLAN 'vid' on top of
- * 'real_dev_name', or NULL if there is no such VLAN device.
- *
- * Changes made by vlandev_add() and vlandev_del() may not be reflected in this
- * function's output without an intervening call to vlandev_refresh(). */
-const char *
-vlandev_get_name(const char *real_dev_name, int vid)
-{
-    const struct vlan_real_dev *real_dev;
-
-    real_dev = shash_find_data(&vlan_real_devs, real_dev_name);
-    if (real_dev) {
-        const struct vlan_dev *vlan_dev;
-
-        HMAP_FOR_EACH_WITH_HASH (vlan_dev, hmap_node, hash_int(vid, 0),
-                                 &real_dev->vlan_devs) {
-            if (vlan_dev->vid == vid) {
-                return vlan_dev->name;
-            }
-        }
-    }
-
-    return NULL;
-}
-\f
-/* The Linux vlandev implementation. */
-
-#ifdef __linux__
-#include "rtnetlink.h"
-#include <linux/if_vlan.h>
-#include <linux/sockios.h>
-#include "netdev-linux.h"
-
-static struct nln_notifier *vlan_cache_notifier;
-static bool cache_valid;
-
-static void
-vlan_cache_cb(const struct rtnetlink_change *change OVS_UNUSED,
-              void *aux OVS_UNUSED)
-{
-    cache_valid = false;
-}
-
-static int
-vlandev_linux_refresh(void)
-{
-    const char *fn = "/proc/net/vlan/config";
-    char line[128];
-    FILE *stream;
-
-    if (!vlan_cache_notifier) {
-        vlan_cache_notifier = rtnetlink_notifier_create(vlan_cache_cb,
-                                                        NULL);
-        if (!vlan_cache_notifier) {
-            return EINVAL;
-        }
-    }
-
-    if (cache_valid) {
-        return 0;
-    }
-
-    vlandev_clear__();
-
-    /* Repopulate cache. */
-    stream = fopen(fn, "r");
-    if (!stream) {
-        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-        int error = errno;
-        struct stat s;
-
-        if (error == ENOENT && !stat("/proc", &s)) {
-            /* Probably the vlan module just isn't loaded, and probably that's
-             * because no VLAN devices have been created.
-             *
-             * Not really an error. */
-            return 0;
-        }
-
-        VLOG_WARN_RL(&rl, "%s: open failed (%s)", fn, ovs_strerror(error));
-        return error;
-    }
-
-    while (fgets(line, sizeof line, stream)) {
-        char vlan_dev[16], real_dev[16];
-        int vid;
-
-        if (ovs_scan(line, "%15[^ |] | %d | %15s", vlan_dev, &vid, real_dev)) {
-            vlandev_add__(vlan_dev, real_dev, vid);
-        }
-    }
-    fclose(stream);
-
-    cache_valid = true;
-    return 0;
-}
-
-static int
-do_vlan_ioctl(const char *netdev_name, struct vlan_ioctl_args *via,
-              int cmd, const char *cmd_name)
-{
-    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-    int error;
-
-    via->cmd = cmd;
-    ovs_strlcpy(via->device1, netdev_name, sizeof via->device1);
-
-    error = af_inet_ioctl(SIOCSIFVLAN, via);
-    if (error) {
-        VLOG_WARN_RL(&rl, "%s: VLAN ioctl %s failed (%s)",
-                     netdev_name, cmd_name, ovs_strerror(error));
-    }
-    return error;
-}
-
-static int
-vlandev_linux_add(const char *real_dev, int vid)
-{
-    struct vlan_ioctl_args via;
-    int error;
-
-    memset(&via, 0, sizeof via);
-    via.u.VID = vid;
-
-    error = do_vlan_ioctl(real_dev, &via, ADD_VLAN_CMD, "ADD_VLAN_CMD");
-    if (!error) {
-        cache_valid = false;
-    }
-    return error;
-}
-
-static int
-vlandev_linux_del(const char *vlan_dev)
-{
-    struct vlan_ioctl_args via;
-    int error;
-
-    memset(&via, 0, sizeof via);
-    error = do_vlan_ioctl(vlan_dev, &via, DEL_VLAN_CMD, "DEL_VLAN_CMD");
-    if (!error) {
-        cache_valid = false;
-    }
-    return error;
-}
-
-static const struct vlandev_class vlandev_linux_class = {
-    vlandev_linux_refresh,
-    vlandev_linux_add,
-    vlandev_linux_del
-};
-#endif
-\f
-/* Stub implementation. */
-
-static int
-vlandev_stub_add(const char *real_dev OVS_UNUSED, int vid OVS_UNUSED)
-{
-    VLOG_ERR("not supported on non-Linux platform");
-    return EOPNOTSUPP;
-}
-
-static int
-vlandev_stub_del(const char *vlan_dev OVS_UNUSED)
-{
-    VLOG_ERR("not supported on non-Linux platform");
-    return EOPNOTSUPP;
-}
-
-static const struct vlandev_class OVS_UNUSED vlandev_stub_class = {
-    NULL,                       /* vd_refresh */
-    vlandev_stub_add,
-    vlandev_stub_del
-};
-\f
-/* Dummy implementation. */
-
-static int
-vlandev_dummy_add(const char *real_dev, int vid)
-{
-    char name[IFNAMSIZ];
-
-    if (snprintf(name, sizeof name, "%s.%d", real_dev, vid) >= sizeof name) {
-        return ENAMETOOLONG;
-    }
-    return vlandev_add__(name, real_dev, vid);
-}
-
-static int
-vlandev_dummy_del(const char *vlan_dev)
-{
-    return vlandev_del__(vlan_dev);
-}
-
-static const struct vlandev_class vlandev_dummy_class = {
-    NULL,                       /* vd_refresh */
-    vlandev_dummy_add,
-    vlandev_dummy_del
-};
-\f
-static int
-vlandev_add__(const char *vlan_dev, const char *real_dev, int vid)
-{
-    uint32_t vid_hash = hash_int(vid, 0);
-    struct vlan_real_dev *vrd;
-    struct vlan_dev *vd;
-
-    if (vid < 0 || vid > 4095) {
-        return EINVAL;
-    } else if (shash_find(&vlan_devs, vlan_dev)) {
-        return EEXIST;
-    }
-
-    vrd = shash_find_data(&vlan_real_devs, real_dev);
-    if (!vrd) {
-        vrd = xmalloc(sizeof *vrd);
-        vrd->name = xstrdup(real_dev);
-        hmap_init(&vrd->vlan_devs);
-        shash_add_nocopy(&vlan_real_devs, vrd->name, vrd);
-    } else {
-        HMAP_FOR_EACH_WITH_HASH (vd, hmap_node, vid_hash, &vrd->vlan_devs) {
-            if (vd->vid == vid) {
-                return EEXIST;
-            }
-        }
-    }
-
-    vd = xmalloc(sizeof *vd);
-    hmap_insert(&vrd->vlan_devs, &vd->hmap_node, vid_hash);
-    vd->name = xstrdup(vlan_dev);
-    vd->vid = vid;
-    vd->real_dev = vrd;
-    shash_add_nocopy(&vlan_devs, vd->name, vd);
-
-    return 0;
-}
-
-static int
-vlandev_del__(const char *vlan_dev)
-{
-    struct shash_node *vd_node = shash_find(&vlan_devs, vlan_dev);
-    if (vd_node) {
-        struct vlan_dev *vd = vd_node->data;
-        struct vlan_real_dev *vrd = vd->real_dev;
-
-        hmap_remove(&vrd->vlan_devs, &vd->hmap_node);
-        if (hmap_is_empty(&vrd->vlan_devs)) {
-            shash_find_and_delete_assert(&vlan_real_devs, vrd->name);
-            free(vrd);
-        }
-
-        shash_delete(&vlan_devs, vd_node);
-        free(vd);
-
-        return 0;
-    } else {
-        return ENOENT;
-    }
-}
-
-/* Clear 'vlan_devs' and 'vlan_real_devs' in preparation for repopulating. */
-static void
-vlandev_clear__(void)
-{
-    /* We do not free the 'name' members of struct vlan_dev and struct
-     * vlan_real_dev, because the "shash"es own them.. */
-    struct shash_node *node;
-
-    shash_clear_free_data(&vlan_devs);
-    SHASH_FOR_EACH (node, &vlan_real_devs) {
-        struct vlan_real_dev *vrd = node->data;
-
-        hmap_destroy(&vrd->vlan_devs);
-    }
-    shash_clear_free_data(&vlan_real_devs);
-}
diff --git a/lib/vlandev.h b/lib/vlandev.h
deleted file mode 100644 (file)
index e25ffcb..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2011 Nicira, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VLANDEV_H
-#define VLANDEV_H 1
-
-#include "hmap.h"
-
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device
- * drivers in old versions of Linux that do not properly support VLANs when
- * VLAN devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-
-/* A VLAN device (e.g. "eth0.10" for VLAN 10 on eth0). */
-struct vlan_dev {
-    struct vlan_real_dev *real_dev; /* Parent, e.g. "eth0". */
-    struct hmap_node hmap_node;     /* In vlan_real_dev's "vlan_devs" map. */
-    char *name;                     /* VLAN device name, e.g. "eth0.10". */
-    int vid;                        /* VLAN ID, e.g. 10. */
-};
-
-/* A device that has VLAN devices broken out of it. */
-struct vlan_real_dev {
-    char *name;                 /* Name, e.g. "eth0". */
-    struct hmap vlan_devs;      /* All child VLAN devices, hashed by VID. */
-};
-
-int vlandev_add(const char *real_dev, int vid);
-int vlandev_del(const char *vlan_dev);
-
-int vlandev_refresh(void);
-struct shash *vlandev_get_real_devs(void);
-const char *vlandev_get_name(const char *real_dev_name, int vid);
-
-#endif /* vlandev.h */
index 2612b7d..f62f46b 100644 (file)
@@ -221,9 +221,6 @@ struct upcall {
     struct dpif_ipfix *ipfix;      /* IPFIX pointer or NULL. */
     struct dpif_sflow *sflow;      /* SFlow pointer or NULL. */
 
-    bool vsp_adjusted;             /* 'packet' and 'flow' were adjusted for
-                                      VLAN splinters if true. */
-
     struct udpif_key *ukey;        /* Revalidator flow cache. */
     bool ukey_persists;            /* Set true to keep 'ukey' beyond the
                                       lifetime of this upcall. */
@@ -791,10 +788,6 @@ recv_upcalls(struct handler *handler)
         upcall->out_tun_key = dupcall->out_tun_key;
         upcall->actions = dupcall->actions;
 
-        if (vsp_adjust_flow(upcall->ofproto, flow, &dupcall->packet)) {
-            upcall->vsp_adjusted = true;
-        }
-
         pkt_metadata_from_flow(&dupcall->packet.md, flow);
         flow_extract(&dupcall->packet, flow);
 
@@ -1037,7 +1030,6 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer,
     ofpbuf_init(&upcall->put_actions, 0);
 
     upcall->xout_initialized = false;
-    upcall->vsp_adjusted = false;
     upcall->ukey_persists = false;
 
     upcall->ukey = NULL;
@@ -1312,21 +1304,6 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
         const struct dp_packet *packet = upcall->packet;
         struct ukey_op *op;
 
-        if (upcall->vsp_adjusted) {
-            /* This packet was received on a VLAN splinter port.  We added a
-             * VLAN to the packet to make the packet resemble the flow, but the
-             * actions were composed assuming that the packet contained no
-             * VLAN.  So, we must remove the VLAN header from the packet before
-             * trying to execute the actions. */
-            if (upcall->odp_actions.size) {
-                eth_pop_vlan(CONST_CAST(struct dp_packet *, upcall->packet));
-            }
-
-            /* Remove the flow vlan tags inserted by vlan splinter logic
-             * to ensure megaflow masks generated match the data path flow. */
-            CONST_CAST(struct flow *, upcall->flow)->vlan_tci = 0;
-        }
-
         /* Do not install a flow into the datapath if:
          *
          *    - The datapath already has too many flows.
index ef770f2..cdf5a83 100644 (file)
@@ -3125,17 +3125,6 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
     } else {
         odp_port = xport->odp_port;
         out_port = odp_port;
-        if (ofproto_has_vlan_splinters(ctx->xbridge->ofproto)) {
-            ofp_port_t vlandev_port;
-
-            wc->masks.vlan_tci |= htons(VLAN_VID_MASK | VLAN_CFI);
-            vlandev_port = vsp_realdev_to_vlandev(ctx->xbridge->ofproto,
-                                                  ofp_port, flow->vlan_tci);
-            if (vlandev_port != ofp_port) {
-                out_port = ofp_port_to_odp_port(ctx->xbridge, vlandev_port);
-                flow->vlan_tci = htons(0);
-            }
-        }
     }
 
     if (out_port != ODPP_NONE) {
@@ -5120,26 +5109,12 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
     };
 
     /* 'base_flow' reflects the packet as it came in, but we need it to reflect
-     * the packet as the datapath will treat it for output actions:
-     *
-     *     - Our datapath doesn't retain tunneling information without us
-     *       re-setting it, so clear the tunnel data.
-     *
-     *     - For VLAN splinters, a higher layer may pretend that the packet
-     *       came in on 'flow->in_port.ofp_port' with 'flow->vlan_tci'
-     *       attached, because that's how we want to treat it from an OpenFlow
-     *       perspective.  But from the datapath's perspective it actually came
-     *       in on a VLAN device without any VLAN attached.  So here we put the
-     *       datapath's view of the VLAN information in 'base_flow' to ensure
-     *       correct treatment.
+     * the packet as the datapath will treat it for output actions. Our
+     * datapath doesn't retain tunneling information without us re-setting
+     * it, so clear the tunnel data.
      */
+
     memset(&ctx.base_flow.tunnel, 0, sizeof ctx.base_flow.tunnel);
-    if (flow->in_port.ofp_port
-        != vsp_realdev_to_vlandev(xbridge->ofproto,
-                                  flow->in_port.ofp_port,
-                                  flow->vlan_tci)) {
-        ctx.base_flow.vlan_tci = 0;
-    }
 
     ofpbuf_reserve(ctx.odp_actions, NL_A_U32_SIZE);
     if (xin->wc) {
index 285e377..a1e0407 100644 (file)
@@ -189,34 +189,8 @@ struct ofport_dpif {
     /* Queue to DSCP mapping. */
     struct ofproto_port_queue *qdscp;
     size_t n_qdscp;
-
-    /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
-     *
-     * This is deprecated.  It is only for compatibility with broken device
-     * drivers in old versions of Linux that do not properly support VLANs when
-     * VLAN devices are not used.  When broken device drivers are no longer in
-     * widespread use, we will delete these interfaces. */
-    ofp_port_t realdev_ofp_port;
-    int vlandev_vid;
 };
 
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device drivers
- * in old versions of Linux that do not properly support VLANs when VLAN
- * devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-struct vlan_splinter {
-    struct hmap_node realdev_vid_node;
-    struct hmap_node vlandev_node;
-    ofp_port_t realdev_ofp_port;
-    ofp_port_t vlandev_ofp_port;
-    int vid;
-};
-
-static void vsp_remove(struct ofport_dpif *);
-static void vsp_add(struct ofport_dpif *, ofp_port_t realdev_ofp_port, int vid);
-
 static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *,
                                        ofp_port_t);
 
@@ -330,11 +304,6 @@ struct ofproto_dpif {
     struct rstp *rstp;
     long long int rstp_last_tick;
 
-    /* VLAN splinters. */
-    struct ovs_mutex vsp_mutex;
-    struct hmap realdev_vid_map OVS_GUARDED; /* (realdev,vid) -> vlandev. */
-    struct hmap vlandev_map OVS_GUARDED;     /* vlandev -> (realdev,vid). */
-
     /* Ports. */
     struct sset ports;             /* Set of standard port names. */
     struct sset ghost_ports;       /* Ports with no datapath port. */
@@ -1329,13 +1298,9 @@ construct(struct ofproto *ofproto_)
     ofproto->has_bonded_bundles = false;
     ofproto->lacp_enabled = false;
     ovs_mutex_init_adaptive(&ofproto->stats_mutex);
-    ovs_mutex_init(&ofproto->vsp_mutex);
 
     guarded_list_init(&ofproto->ams);
 
-    hmap_init(&ofproto->vlandev_map);
-    hmap_init(&ofproto->realdev_vid_map);
-
     sset_init(&ofproto->ports);
     sset_init(&ofproto->ghost_ports);
     sset_init(&ofproto->port_poll_set);
@@ -1487,15 +1452,11 @@ destruct(struct ofproto *ofproto_)
     mac_learning_unref(ofproto->ml);
     mcast_snooping_unref(ofproto->ms);
 
-    hmap_destroy(&ofproto->vlandev_map);
-    hmap_destroy(&ofproto->realdev_vid_map);
-
     sset_destroy(&ofproto->ports);
     sset_destroy(&ofproto->ghost_ports);
     sset_destroy(&ofproto->port_poll_set);
 
     ovs_mutex_destroy(&ofproto->stats_mutex);
-    ovs_mutex_destroy(&ofproto->vsp_mutex);
 
     seq_destroy(ofproto->ams_seq);
 
@@ -1737,8 +1698,6 @@ port_construct(struct ofport *port_)
     port->peer = NULL;
     port->qdscp = NULL;
     port->n_qdscp = 0;
-    port->realdev_ofp_port = 0;
-    port->vlandev_vid = 0;
     port->carrier_seq = netdev_get_carrier_resets(netdev);
     port->is_layer3 = netdev_vport_is_layer3(netdev);
 
@@ -4902,9 +4861,6 @@ parse_flow_and_packet(int argc, const char *argv[],
             error = "Invalid datapath flow";
             goto exit;
         }
-
-        vsp_adjust_flow(*ofprotop, flow, NULL);
-
     } else {
         char *err = parse_ofp_exact_flow(flow, NULL, argv[argc - 1], NULL);
 
@@ -5414,239 +5370,6 @@ table_is_internal(uint8_t table_id)
     return table_id == TBL_INTERNAL;
 }
 \f
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device drivers
- * in old versions of Linux that do not properly support VLANs when VLAN
- * devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-
-static int
-set_realdev(struct ofport *ofport_, ofp_port_t realdev_ofp_port, int vid)
-{
-    struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport_->ofproto);
-    struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
-
-    if (realdev_ofp_port == ofport->realdev_ofp_port
-        && vid == ofport->vlandev_vid) {
-        return 0;
-    }
-
-    ofproto->backer->need_revalidate = REV_RECONFIGURE;
-
-    if (ofport->realdev_ofp_port) {
-        vsp_remove(ofport);
-    }
-    if (realdev_ofp_port && ofport->bundle) {
-        /* vlandevs are enslaved to their realdevs, so they are not allowed to
-         * themselves be part of a bundle. */
-        bundle_set(ofport_->ofproto, ofport->bundle, NULL);
-    }
-
-    ofport->realdev_ofp_port = realdev_ofp_port;
-    ofport->vlandev_vid = vid;
-
-    if (realdev_ofp_port) {
-        vsp_add(ofport, realdev_ofp_port, vid);
-    }
-
-    return 0;
-}
-
-static uint32_t
-hash_realdev_vid(ofp_port_t realdev_ofp_port, int vid)
-{
-    return hash_2words(ofp_to_u16(realdev_ofp_port), vid);
-}
-
-bool
-ofproto_has_vlan_splinters(const struct ofproto_dpif *ofproto)
-    OVS_EXCLUDED(ofproto->vsp_mutex)
-{
-    /* hmap_is_empty is thread safe. */
-    return !hmap_is_empty(&ofproto->realdev_vid_map);
-}
-
-
-static ofp_port_t
-vsp_realdev_to_vlandev__(const struct ofproto_dpif *ofproto,
-                         ofp_port_t realdev_ofp_port, ovs_be16 vlan_tci)
-    OVS_REQUIRES(ofproto->vsp_mutex)
-{
-    if (!hmap_is_empty(&ofproto->realdev_vid_map)) {
-        int vid = vlan_tci_to_vid(vlan_tci);
-        const struct vlan_splinter *vsp;
-
-        HMAP_FOR_EACH_WITH_HASH (vsp, realdev_vid_node,
-                                 hash_realdev_vid(realdev_ofp_port, vid),
-                                 &ofproto->realdev_vid_map) {
-            if (vsp->realdev_ofp_port == realdev_ofp_port
-                && vsp->vid == vid) {
-                return vsp->vlandev_ofp_port;
-            }
-        }
-    }
-    return realdev_ofp_port;
-}
-
-/* Returns the OFP port number of the Linux VLAN device that corresponds to
- * 'vlan_tci' on the network device with port number 'realdev_ofp_port' in
- * 'struct ofport_dpif'.  For example, given 'realdev_ofp_port' of eth0 and
- * 'vlan_tci' 9, it would return the port number of eth0.9.
- *
- * Unless VLAN splinters are enabled for port 'realdev_ofp_port', this
- * function just returns its 'realdev_ofp_port' argument. */
-ofp_port_t
-vsp_realdev_to_vlandev(const struct ofproto_dpif *ofproto,
-                       ofp_port_t realdev_ofp_port, ovs_be16 vlan_tci)
-    OVS_EXCLUDED(ofproto->vsp_mutex)
-{
-    ofp_port_t ret;
-
-    /* hmap_is_empty is thread safe, see if we can return immediately. */
-    if (hmap_is_empty(&ofproto->realdev_vid_map)) {
-        return realdev_ofp_port;
-    }
-    ovs_mutex_lock(&ofproto->vsp_mutex);
-    ret = vsp_realdev_to_vlandev__(ofproto, realdev_ofp_port, vlan_tci);
-    ovs_mutex_unlock(&ofproto->vsp_mutex);
-    return ret;
-}
-
-static struct vlan_splinter *
-vlandev_find(const struct ofproto_dpif *ofproto, ofp_port_t vlandev_ofp_port)
-{
-    struct vlan_splinter *vsp;
-
-    HMAP_FOR_EACH_WITH_HASH (vsp, vlandev_node,
-                             hash_ofp_port(vlandev_ofp_port),
-                             &ofproto->vlandev_map) {
-        if (vsp->vlandev_ofp_port == vlandev_ofp_port) {
-            return vsp;
-        }
-    }
-
-    return NULL;
-}
-
-/* Returns the OpenFlow port number of the "real" device underlying the Linux
- * VLAN device with OpenFlow port number 'vlandev_ofp_port' and stores the
- * VLAN VID of the Linux VLAN device in '*vid'.  For example, given
- * 'vlandev_ofp_port' of eth0.9, it would return the OpenFlow port number of
- * eth0 and store 9 in '*vid'.
- *
- * Returns 0 and does not modify '*vid' if 'vlandev_ofp_port' is not a Linux
- * VLAN device.  Unless VLAN splinters are enabled, this is what this function
- * always does.*/
-static ofp_port_t
-vsp_vlandev_to_realdev(const struct ofproto_dpif *ofproto,
-                       ofp_port_t vlandev_ofp_port, int *vid)
-    OVS_REQUIRES(ofproto->vsp_mutex)
-{
-    if (!hmap_is_empty(&ofproto->vlandev_map)) {
-        const struct vlan_splinter *vsp;
-
-        vsp = vlandev_find(ofproto, vlandev_ofp_port);
-        if (vsp) {
-            if (vid) {
-                *vid = vsp->vid;
-            }
-            return vsp->realdev_ofp_port;
-        }
-    }
-    return 0;
-}
-
-/* Given 'flow', a flow representing a packet received on 'ofproto', checks
- * whether 'flow->in_port' represents a Linux VLAN device.  If so, changes
- * 'flow->in_port' to the "real" device backing the VLAN device, sets
- * 'flow->vlan_tci' to the VLAN VID, and returns true.  Optionally pushes the
- * appropriate VLAN on 'packet' if provided.  Otherwise (which is always the
- * case unless VLAN splinters are enabled), returns false without making any
- * changes. */
-bool
-vsp_adjust_flow(const struct ofproto_dpif *ofproto, struct flow *flow,
-                struct dp_packet *packet)
-    OVS_EXCLUDED(ofproto->vsp_mutex)
-{
-    ofp_port_t realdev;
-    int vid;
-
-    /* hmap_is_empty is thread safe. */
-    if (hmap_is_empty(&ofproto->vlandev_map)) {
-        return false;
-    }
-
-    ovs_mutex_lock(&ofproto->vsp_mutex);
-    realdev = vsp_vlandev_to_realdev(ofproto, flow->in_port.ofp_port, &vid);
-    ovs_mutex_unlock(&ofproto->vsp_mutex);
-    if (!realdev) {
-        return false;
-    }
-
-    /* Cause the flow to be processed as if it came in on the real device with
-     * the VLAN device's VLAN ID. */
-    flow->in_port.ofp_port = realdev;
-    flow->vlan_tci = htons((vid & VLAN_VID_MASK) | VLAN_CFI);
-
-    if (packet) {
-        /* Make the packet resemble the flow, so that it gets sent to an
-         * OpenFlow controller properly, so that it looks correct for sFlow,
-         * and so that flow_extract() will get the correct vlan_tci if it is
-         * called on 'packet'. */
-        eth_push_vlan(packet, htons(ETH_TYPE_VLAN), flow->vlan_tci);
-    }
-
-    return true;
-}
-
-static void
-vsp_remove(struct ofport_dpif *port)
-{
-    struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
-    struct vlan_splinter *vsp;
-
-    ovs_mutex_lock(&ofproto->vsp_mutex);
-    vsp = vlandev_find(ofproto, port->up.ofp_port);
-    if (vsp) {
-        hmap_remove(&ofproto->vlandev_map, &vsp->vlandev_node);
-        hmap_remove(&ofproto->realdev_vid_map, &vsp->realdev_vid_node);
-        free(vsp);
-
-        port->realdev_ofp_port = 0;
-    } else {
-        VLOG_ERR("missing vlan device record");
-    }
-    ovs_mutex_unlock(&ofproto->vsp_mutex);
-}
-
-static void
-vsp_add(struct ofport_dpif *port, ofp_port_t realdev_ofp_port, int vid)
-{
-    struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
-
-    ovs_mutex_lock(&ofproto->vsp_mutex);
-    if (!vsp_vlandev_to_realdev(ofproto, port->up.ofp_port, NULL)
-        && (vsp_realdev_to_vlandev__(ofproto, realdev_ofp_port, htons(vid))
-            == realdev_ofp_port)) {
-        struct vlan_splinter *vsp;
-
-        vsp = xmalloc(sizeof *vsp);
-        vsp->realdev_ofp_port = realdev_ofp_port;
-        vsp->vlandev_ofp_port = port->up.ofp_port;
-        vsp->vid = vid;
-
-        port->realdev_ofp_port = realdev_ofp_port;
-
-        hmap_insert(&ofproto->vlandev_map, &vsp->vlandev_node,
-                    hash_ofp_port(port->up.ofp_port));
-        hmap_insert(&ofproto->realdev_vid_map, &vsp->realdev_vid_node,
-                    hash_realdev_vid(realdev_ofp_port, vid));
-    } else {
-        VLOG_ERR("duplicate vlan device record");
-    }
-    ovs_mutex_unlock(&ofproto->vsp_mutex);
-}
 
 static odp_port_t
 ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port)
@@ -5845,7 +5568,6 @@ const struct ofproto_class ofproto_dpif_class = {
     set_mac_table_config,
     set_mcast_snooping,
     set_mcast_snooping_port,
-    set_realdev,
     NULL,                       /* meter_get_features */
     NULL,                       /* meter_set */
     NULL,                       /* meter_get */
index 91bf463..adcbedb 100644 (file)
@@ -143,13 +143,6 @@ const char *group_dpif_get_selection_method(const struct group_dpif *group);
 uint64_t group_dpif_get_selection_method_param(const struct group_dpif *group);
 const struct field_array *group_dpif_get_fields(const struct group_dpif *group);
 
-bool ofproto_has_vlan_splinters(const struct ofproto_dpif *);
-ofp_port_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
-                                  ofp_port_t realdev_ofp_port,
-                                  ovs_be16 vlan_tci);
-bool vsp_adjust_flow(const struct ofproto_dpif *, struct flow *,
-                     struct dp_packet *packet);
-
 int ofproto_dpif_execute_actions(struct ofproto_dpif *, const struct flow *,
                                  struct rule_dpif *, const struct ofpact *,
                                  size_t ofpacts_len, struct dp_packet *);
index daa0077..d7fd50e 100644 (file)
@@ -121,14 +121,6 @@ struct ofproto {
      * the flow table and reacquire the global lock. */
     struct guarded_list rule_executes; /* Contains "struct rule_execute"s. */
 
-    /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
-     *
-     * This is deprecated.  It is only for compatibility with broken device
-     * drivers in old versions of Linux that do not properly support VLANs when
-     * VLAN devices are not used.  When broken device drivers are no longer in
-     * widespread use, we will delete these interfaces. */
-    unsigned long int *vlan_bitmap; /* 4096-bit bitmap of in-use VLANs. */
-    bool vlans_changed;             /* True if new VLANs are in use. */
     int min_mtu;                    /* Current MTU of non-internal ports. */
 
     /* Groups. */
@@ -1704,25 +1696,6 @@ struct ofproto_class {
     int (*set_mcast_snooping_port)(struct ofproto *ofproto_, void *aux,
                           const struct ofproto_mcast_snooping_port_settings *s);
 
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device drivers
- * in old versions of Linux that do not properly support VLANs when VLAN
- * devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-
-    /* If 'realdev_ofp_port' is nonzero, then this function configures 'ofport'
-     * as a VLAN splinter port for VLAN 'vid', associated with the real device
-     * that has OpenFlow port number 'realdev_ofp_port'.
-     *
-     * If 'realdev_ofp_port' is zero, then this function deconfigures 'ofport'
-     * as a VLAN splinter port.
-     *
-     * This function should be NULL if an implementation does not support it.
-     */
-    int (*set_realdev)(struct ofport *ofport,
-                       ofp_port_t realdev_ofp_port, int vid);
-
 /* ## ------------------------ ## */
 /* ## OpenFlow meter functions ## */
 /* ## ------------------------ ## */
index 89e75d5..ae527a4 100644 (file)
@@ -560,8 +560,6 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
     ovs_list_init(&ofproto->expirable);
     ofproto->connmgr = connmgr_create(ofproto, datapath_name, datapath_name);
     guarded_list_init(&ofproto->rule_executes);
-    ofproto->vlan_bitmap = NULL;
-    ofproto->vlans_changed = false;
     ofproto->min_mtu = INT_MAX;
     ovs_rwlock_init(&ofproto->groups_rwlock);
     hmap_init(&ofproto->groups);
@@ -1558,8 +1556,6 @@ ofproto_destroy__(struct ofproto *ofproto)
     ovs_assert(hmap_is_empty(&ofproto->learned_cookies));
     hmap_destroy(&ofproto->learned_cookies);
 
-    free(ofproto->vlan_bitmap);
-
     ofproto->ofproto_class->dealloc(ofproto);
 }
 
@@ -2445,9 +2441,6 @@ ofproto_port_unregister(struct ofproto *ofproto, ofp_port_t ofp_port)
 {
     struct ofport *port = ofproto_get_port(ofproto, ofp_port);
     if (port) {
-        if (port->ofproto->ofproto_class->set_realdev) {
-            port->ofproto->ofproto_class->set_realdev(port, 0, 0);
-        }
         if (port->ofproto->ofproto_class->set_stp_port) {
             port->ofproto->ofproto_class->set_stp_port(port, NULL);
         }
@@ -4715,19 +4708,6 @@ add_flow_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm,
     if (old_rule) {
         ovsrcu_postpone(remove_rule_rcu, old_rule);
     } else {
-        if (minimask_get_vid_mask(new_rule->cr.match.mask) == VLAN_VID_MASK) {
-            if (ofproto->vlan_bitmap) {
-                uint16_t vid = miniflow_get_vid(new_rule->cr.match.flow);
-
-                if (!bitmap_is_set(ofproto->vlan_bitmap, vid)) {
-                    bitmap_set1(ofproto->vlan_bitmap, vid);
-                    ofproto->vlans_changed = true;
-                }
-            } else {
-                ofproto->vlans_changed = true;
-            }
-        }
-
         ofmonitor_report(ofproto->connmgr, new_rule, NXFME_ADDED, 0,
                          req ? req->ofconn : NULL,
                          req ? req->request->xid : 0, NULL);
@@ -7921,92 +7901,3 @@ ofproto_unixctl_init(void)
     unixctl_command_register("ofproto/list", "", 0, 0,
                              ofproto_unixctl_list, NULL);
 }
-\f
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device drivers
- * in old versions of Linux that do not properly support VLANs when VLAN
- * devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-
-/* Sets a 1-bit in the 4096-bit 'vlan_bitmap' for each VLAN ID that is matched
- * (exactly) by an OpenFlow rule in 'ofproto'. */
-void
-ofproto_get_vlan_usage(struct ofproto *ofproto, unsigned long int *vlan_bitmap)
-{
-    struct match match;
-    struct cls_rule target;
-    const struct oftable *oftable;
-
-    match_init_catchall(&match);
-    match_set_vlan_vid_masked(&match, htons(VLAN_CFI), htons(VLAN_CFI));
-    cls_rule_init(&target, &match, 0);
-
-    free(ofproto->vlan_bitmap);
-    ofproto->vlan_bitmap = bitmap_allocate(4096);
-    ofproto->vlans_changed = false;
-
-    OFPROTO_FOR_EACH_TABLE (oftable, ofproto) {
-        struct rule *rule;
-
-        CLS_FOR_EACH_TARGET (rule, cr, &oftable->cls, &target,
-                             CLS_MAX_VERSION) {
-            if (minimask_get_vid_mask(rule->cr.match.mask) == VLAN_VID_MASK) {
-                uint16_t vid = miniflow_get_vid(rule->cr.match.flow);
-
-                bitmap_set1(vlan_bitmap, vid);
-                bitmap_set1(ofproto->vlan_bitmap, vid);
-            }
-        }
-    }
-
-    cls_rule_destroy(&target);
-}
-
-/* Returns true if new VLANs have come into use by the flow table since the
- * last call to ofproto_get_vlan_usage().
- *
- * We don't track when old VLANs stop being used. */
-bool
-ofproto_has_vlan_usage_changed(const struct ofproto *ofproto)
-{
-    return ofproto->vlans_changed;
-}
-
-/* Configures a VLAN splinter binding between the ports identified by OpenFlow
- * port numbers 'vlandev_ofp_port' and 'realdev_ofp_port'.  If
- * 'realdev_ofp_port' is nonzero, then the VLAN device is enslaved to the real
- * device as a VLAN splinter for VLAN ID 'vid'.  If 'realdev_ofp_port' is zero,
- * then the VLAN device is un-enslaved. */
-int
-ofproto_port_set_realdev(struct ofproto *ofproto, ofp_port_t vlandev_ofp_port,
-                         ofp_port_t realdev_ofp_port, int vid)
-{
-    struct ofport *ofport;
-    int error;
-
-    ovs_assert(vlandev_ofp_port != realdev_ofp_port);
-
-    ofport = ofproto_get_port(ofproto, vlandev_ofp_port);
-    if (!ofport) {
-        VLOG_WARN("%s: cannot set realdev on nonexistent port %"PRIu16,
-                  ofproto->name, vlandev_ofp_port);
-        return EINVAL;
-    }
-
-    if (!ofproto->ofproto_class->set_realdev) {
-        if (!vlandev_ofp_port) {
-            return 0;
-        }
-        VLOG_WARN("%s: vlan splinters not supported", ofproto->name);
-        return EOPNOTSUPP;
-    }
-
-    error = ofproto->ofproto_class->set_realdev(ofport, realdev_ofp_port, vid);
-    if (error) {
-        VLOG_WARN("%s: setting realdev on port %"PRIu16" (%s) failed (%s)",
-                  ofproto->name, vlandev_ofp_port,
-                  netdev_get_name(ofport->netdev), ovs_strerror(error));
-    }
-    return error;
-}
index 2d241c9..8588872 100644 (file)
@@ -399,14 +399,6 @@ struct ofproto_bundle_settings {
 
     struct lacp_settings *lacp;              /* Nonnull to enable LACP. */
     struct lacp_slave_settings *lacp_slaves; /* Array of n_slaves elements. */
-
-    /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
-     *
-     * This is deprecated.  It is only for compatibility with broken device
-     * drivers in old versions of Linux that do not properly support VLANs when
-     * VLAN devices are not used.  When broken device drivers are no longer in
-     * widespread use, we will delete these interfaces. */
-    ofp_port_t realdev_ofp_port;/* OpenFlow port number of real device. */
 };
 
 int ofproto_bundle_register(struct ofproto *, void *aux,
@@ -504,18 +496,6 @@ int ofproto_port_get_cfm_status(const struct ofproto *,
                                 ofp_port_t ofp_port,
                                 struct cfm_status *);
 \f
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device drivers
- * in old versions of Linux that do not properly support VLANs when VLAN
- * devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-
-void ofproto_get_vlan_usage(struct ofproto *, unsigned long int *vlan_bitmap);
-bool ofproto_has_vlan_usage_changed(const struct ofproto *);
-int ofproto_port_set_realdev(struct ofproto *, ofp_port_t vlandev_ofp_port,
-                             ofp_port_t realdev_ofp_port, int vid);
-\f
 /* Table configuration */
 
 enum ofputil_table_miss ofproto_table_get_miss_config(const struct ofproto *,
index aed032b..0b77617 100644 (file)
@@ -58,7 +58,6 @@ TESTSUITE_AT = \
        tests/dpctl.at \
        tests/ofproto-dpif.at \
        tests/bridge.at \
-       tests/vlan-splinters.at \
        tests/ofproto.at \
        tests/ovsdb.at \
        tests/ovsdb-log.at \
index 7e3f193..7ac74df 100644 (file)
@@ -57,7 +57,6 @@ m4_include([tests/dpif-netdev.at])
 m4_include([tests/dpctl.at])
 m4_include([tests/ofproto-dpif.at])
 m4_include([tests/bridge.at])
-m4_include([tests/vlan-splinters.at])
 m4_include([tests/ovsdb.at])
 m4_include([tests/ovs-vsctl.at])
 m4_include([tests/ovs-monitor-ipsec.at])
diff --git a/tests/vlan-splinters.at b/tests/vlan-splinters.at
deleted file mode 100644 (file)
index bab7627..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-AT_BANNER([VLAN splinters])
-
-AT_SETUP([VLAN splinters])
-AT_SKIP_IF([test "$IS_WIN32" = "yes"])
-OVS_VSWITCHD_START([], [], [=override])
-add_of_ports br0 1 2 3 4
-AT_CHECK([ovs-vsctl \
-  -- set Bridge br0 fail-mode=standalone flood_vlans=0,9,11,15 \
-  -- set port br0 tag=0 \
-  -- set port p1 trunks=0,9,11,15 \
-  -- set interface p1 other-config:enable-vlan-splinters=true \
-  -- set port p2 tag=9 \
-  -- set port p3 tag=11 \
-  -- set port p4 tag=15])
-
-ovs-appctl dpif/show | sed -n '
-s/\./_/g
-s/^[[  ]]*\([[^        ]][[^   ]]*\) [[0-9]]*\/\([[0-9]]*\).*/\1=\2/p
-' > port-numbers
-cat port-numbers
-. ./port-numbers
-
-for args in '9 p2' '11 p3' '15 p4'; do
-    set $args
-    vlan=$1
-    eval access_port=\$$2
-    eval splinter_port=\$p1_$vlan
-
-    # Check that when a packet is received on $splinter_port, it is
-    # treated as if it had been received on p1 in the correct VLAN.
-    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "in_port($splinter_port)"],
-             [0], [stdout])
-    AT_CHECK_UNQUOTED([sed -n '/^Flow/p; /^Datapath/p' stdout], [0], [dnl
-Flow: in_port=$p1,dl_vlan=$vlan,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x05ff
-Datapath actions: $access_port
-])
-
-    # Check that when an OpenFlow action sends a packet to p1 on
-    # splintered VLAN $vlan, it is actually output to $splinter_port.
-    AT_CHECK([ovs-appctl ofproto/trace ovs-dummy "in_port($access_port)"],
-             [0], [stdout])
-    AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: $splinter_port
-])
-done
-
-OVS_VSWITCHD_STOP
-AT_CLEANUP
index 700f65c..439ca94 100644 (file)
@@ -64,7 +64,6 @@
 #include "timeval.h"
 #include "util.h"
 #include "unixctl.h"
-#include "vlandev.h"
 #include "lib/vswitch-idl.h"
 #include "xenserver.h"
 #include "vlan-bitmap.h"
@@ -234,7 +233,6 @@ static unixctl_cb_func bridge_unixctl_reconnect;
 static size_t bridge_get_controllers(const struct bridge *br,
                                      struct ovsrec_controller ***controllersp);
 static void bridge_collect_wanted_ports(struct bridge *,
-                                        const unsigned long *splinter_vlans,
                                         struct shash *wanted_ports);
 static void bridge_delete_ofprotos(void);
 static void bridge_delete_or_reconfigure_ports(struct bridge *);
@@ -320,24 +318,6 @@ static ofp_port_t iface_get_requested_ofp_port(
 static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *);
 
 
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device drivers
- * in old versions of Linux that do not properly support VLANs when VLAN
- * devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-
-/* True if VLAN splinters are enabled on any interface, false otherwise.*/
-static bool vlan_splinters_enabled_anywhere;
-
-static bool vlan_splinters_is_enabled(const struct ovsrec_interface *);
-static unsigned long int *collect_splinter_vlans(
-    const struct ovsrec_open_vswitch *);
-static void configure_splinter_port(struct port *);
-static void add_vlan_splinter_ports(struct bridge *,
-                                    const unsigned long int *splinter_vlans,
-                                    struct shash *ports);
-
 static void discover_types(const struct ovsrec_open_vswitch *cfg);
 
 static void
@@ -572,7 +552,6 @@ collect_in_band_managers(const struct ovsrec_open_vswitch *ovs_cfg,
 static void
 bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
 {
-    unsigned long int *splinter_vlans;
     struct sockaddr_in *managers;
     struct bridge *br, *next;
     int sflow_bridge_number;
@@ -596,12 +575,10 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
      * This is mostly an update to bridge data structures. Nothing is pushed
      * down to ofproto or lower layers. */
     add_del_bridges(ovs_cfg);
-    splinter_vlans = collect_splinter_vlans(ovs_cfg);
     HMAP_FOR_EACH (br, node, &all_bridges) {
-        bridge_collect_wanted_ports(br, splinter_vlans, &br->wanted_ports);
+        bridge_collect_wanted_ports(br, &br->wanted_ports);
         bridge_del_ports(br, &br->wanted_ports);
     }
-    free(splinter_vlans);
 
     /* Start pushing configuration changes down to the ofproto layer:
      *
@@ -918,11 +895,6 @@ port_configure(struct port *port)
     struct ofproto_bundle_settings s;
     struct iface *iface;
 
-    if (cfg->vlan_mode && !strcmp(cfg->vlan_mode, "splinter")) {
-        configure_splinter_port(port);
-        return;
-    }
-
     /* Get name. */
     s.name = port->name;
 
@@ -1749,7 +1721,6 @@ iface_set_netdev_config(const struct ovsrec_interface *iface_cfg,
 static int
 iface_do_create(const struct bridge *br,
                 const struct ovsrec_interface *iface_cfg,
-                const struct ovsrec_port *port_cfg,
                 ofp_port_t *ofp_portp, struct netdev **netdevp,
                 char **errp)
 {
@@ -1785,10 +1756,6 @@ iface_do_create(const struct bridge *br,
     VLOG_INFO("bridge %s: added interface %s on port %d",
               br->name, iface_cfg->name, *ofp_portp);
 
-    if (port_cfg->vlan_mode && !strcmp(port_cfg->vlan_mode, "splinter")) {
-        netdev_turn_flags_on(netdev, NETDEV_UP, NULL);
-    }
-
     *netdevp = netdev;
     return 0;
 
@@ -1817,7 +1784,7 @@ iface_create(struct bridge *br, const struct ovsrec_interface *iface_cfg,
 
     /* Do the bits that can fail up front. */
     ovs_assert(!iface_lookup(br, iface_cfg->name));
-    error = iface_do_create(br, iface_cfg, port_cfg, &ofp_port, &netdev, &errp);
+    error = iface_do_create(br, iface_cfg, &ofp_port, &netdev, &errp);
     if (error) {
         iface_clear_db_record(iface_cfg, errp);
         free(errp);
@@ -2895,8 +2862,6 @@ bridge_run(void)
     static struct ovsrec_open_vswitch null_cfg;
     const struct ovsrec_open_vswitch *cfg;
 
-    bool vlan_splinters_changed;
-
     ovsrec_open_vswitch_init(&null_cfg);
 
     ovsdb_idl_run(idl);
@@ -2955,22 +2920,7 @@ bridge_run(void)
         stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert);
     }
 
-    /* If VLAN splinters are in use, then we need to reconfigure if VLAN
-     * usage has changed. */
-    vlan_splinters_changed = false;
-    if (vlan_splinters_enabled_anywhere) {
-        struct bridge *br;
-
-        HMAP_FOR_EACH (br, node, &all_bridges) {
-            if (ofproto_has_vlan_usage_changed(br->ofproto)) {
-                vlan_splinters_changed = true;
-                break;
-            }
-        }
-    }
-
-    if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed
-        || ifaces_changed) {
+    if (ovsdb_idl_get_seqno(idl) != idl_seqno || ifaces_changed) {
         struct ovsdb_idl_txn *txn;
 
         ifaces_changed = false;
@@ -3348,7 +3298,6 @@ bridge_get_controllers(const struct bridge *br,
 
 static void
 bridge_collect_wanted_ports(struct bridge *br,
-                            const unsigned long int *splinter_vlans,
                             struct shash *wanted_ports)
 {
     size_t i;
@@ -3381,10 +3330,6 @@ bridge_collect_wanted_ports(struct bridge *br,
 
         shash_add(wanted_ports, br->name, &br->synth_local_port);
     }
-
-    if (splinter_vlans) {
-        add_vlan_splinter_ports(br, splinter_vlans, wanted_ports);
-    }
 }
 
 /* Deletes "struct port"s and "struct iface"s under 'br' which aren't
@@ -4817,278 +4762,8 @@ mirror_configure(struct mirror *m)
 
     return true;
 }
-\f
-/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
- *
- * This is deprecated.  It is only for compatibility with broken device drivers
- * in old versions of Linux that do not properly support VLANs when VLAN
- * devices are not used.  When broken device drivers are no longer in
- * widespread use, we will delete these interfaces. */
-
-static struct ovsrec_port **recs;
-static size_t n_recs, allocated_recs;
-
-/* Adds 'rec' to a list of recs that have to be destroyed when the VLAN
- * splinters are reconfigured. */
-static void
-register_rec(struct ovsrec_port *rec)
-{
-    if (n_recs >= allocated_recs) {
-        recs = x2nrealloc(recs, &allocated_recs, sizeof *recs);
-    }
-    recs[n_recs++] = rec;
-}
-
-/* Frees all of the ports registered with register_reg(). */
-static void
-free_registered_recs(void)
-{
-    size_t i;
-
-    for (i = 0; i < n_recs; i++) {
-        struct ovsrec_port *port = recs[i];
-        size_t j;
-
-        for (j = 0; j < port->n_interfaces; j++) {
-            struct ovsrec_interface *iface = port->interfaces[j];
-            free(iface->name);
-            free(iface);
-        }
-
-        smap_destroy(&port->other_config);
-        free(port->interfaces);
-        free(port->name);
-        free(port->tag);
-        free(port);
-    }
-    n_recs = 0;
-}
-
-/* Returns true if VLAN splinters are enabled on 'iface_cfg', false
- * otherwise. */
-static bool
-vlan_splinters_is_enabled(const struct ovsrec_interface *iface_cfg)
-{
-    return smap_get_bool(&iface_cfg->other_config, "enable-vlan-splinters",
-                         false);
-}
-
-/* Figures out the set of VLANs that are in use for the purpose of VLAN
- * splinters.
- *
- * If VLAN splinters are enabled on at least one interface and any VLANs are in
- * use, returns a 4096-bit bitmap with a 1-bit for each in-use VLAN (bits 0 and
- * 4095 will not be set).  The caller is responsible for freeing the bitmap,
- * with free().
- *
- * If VLANs splinters are not enabled on any interface or if no VLANs are in
- * use, returns NULL.
- *
- * Updates 'vlan_splinters_enabled_anywhere'. */
-static unsigned long int *
-collect_splinter_vlans(const struct ovsrec_open_vswitch *ovs_cfg)
-{
-    unsigned long int *splinter_vlans;
-    struct sset splinter_ifaces;
-    const char *real_dev_name;
-    struct shash *real_devs;
-    struct shash_node *node;
-    struct bridge *br;
-    size_t i;
-
-    /* Free space allocated for synthesized ports and interfaces, since we're
-     * in the process of reconstructing all of them. */
-    free_registered_recs();
-
-    splinter_vlans = bitmap_allocate(4096);
-    sset_init(&splinter_ifaces);
-    vlan_splinters_enabled_anywhere = false;
-    for (i = 0; i < ovs_cfg->n_bridges; i++) {
-        struct ovsrec_bridge *br_cfg = ovs_cfg->bridges[i];
-        size_t j;
-
-        for (j = 0; j < br_cfg->n_ports; j++) {
-            struct ovsrec_port *port_cfg = br_cfg->ports[j];
-            int k;
-
-            for (k = 0; k < port_cfg->n_interfaces; k++) {
-                struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
-
-                if (vlan_splinters_is_enabled(iface_cfg)) {
-                    vlan_splinters_enabled_anywhere = true;
-                    sset_add(&splinter_ifaces, iface_cfg->name);
-                    vlan_bitmap_from_array__(port_cfg->trunks,
-                                             port_cfg->n_trunks,
-                                             splinter_vlans);
-                }
-            }
-
-            if (port_cfg->tag && *port_cfg->tag > 0 && *port_cfg->tag < 4095) {
-                bitmap_set1(splinter_vlans, *port_cfg->tag);
-            }
-        }
-    }
-
-    if (!vlan_splinters_enabled_anywhere) {
-        free(splinter_vlans);
-        sset_destroy(&splinter_ifaces);
-        return NULL;
-    }
-
-    HMAP_FOR_EACH (br, node, &all_bridges) {
-        if (br->ofproto) {
-            ofproto_get_vlan_usage(br->ofproto, splinter_vlans);
-        }
-    }
-
-    /* Don't allow VLANs 0 or 4095 to be splintered.  VLAN 0 should appear on
-     * the real device.  VLAN 4095 is reserved and Linux doesn't allow a VLAN
-     * device to be created for it. */
-    bitmap_set0(splinter_vlans, 0);
-    bitmap_set0(splinter_vlans, 4095);
-
-    /* Delete all VLAN devices that we don't need. */
-    vlandev_refresh();
-    real_devs = vlandev_get_real_devs();
-    SHASH_FOR_EACH (node, real_devs) {
-        const struct vlan_real_dev *real_dev = node->data;
-        const struct vlan_dev *vlan_dev;
-        bool real_dev_has_splinters;
-
-        real_dev_has_splinters = sset_contains(&splinter_ifaces,
-                                               real_dev->name);
-        HMAP_FOR_EACH (vlan_dev, hmap_node, &real_dev->vlan_devs) {
-            if (!real_dev_has_splinters
-                || !bitmap_is_set(splinter_vlans, vlan_dev->vid)) {
-                struct netdev *netdev;
-
-                if (!netdev_open(vlan_dev->name, "system", &netdev)) {
-                    if (!netdev_get_addr_list(netdev, NULL, NULL, NULL)) {
-                        /* It has an IP address configured, so we don't own
-                         * it.  Don't delete it. */
-                    } else {
-                        vlandev_del(vlan_dev->name);
-                    }
-                    netdev_close(netdev);
-                }
-            }
-
-        }
-    }
-
-    /* Add all VLAN devices that we need. */
-    SSET_FOR_EACH (real_dev_name, &splinter_ifaces) {
-        int vid;
-
-        BITMAP_FOR_EACH_1 (vid, 4096, splinter_vlans) {
-            if (!vlandev_get_name(real_dev_name, vid)) {
-                vlandev_add(real_dev_name, vid);
-            }
-        }
-    }
-
-    vlandev_refresh();
-
-    sset_destroy(&splinter_ifaces);
-
-    if (bitmap_scan(splinter_vlans, 1, 0, 4096) >= 4096) {
-        free(splinter_vlans);
-        return NULL;
-    }
-    return splinter_vlans;
-}
-
-/* Pushes the configure of VLAN splinter port 'port' (e.g. eth0.9) down to
- * ofproto.  */
-static void
-configure_splinter_port(struct port *port)
-{
-    struct ofproto *ofproto = port->bridge->ofproto;
-    ofp_port_t realdev_ofp_port;
-    const char *realdev_name;
-    struct iface *vlandev, *realdev;
-
-    ofproto_bundle_unregister(port->bridge->ofproto, port);
-
-    vlandev = CONTAINER_OF(ovs_list_front(&port->ifaces), struct iface,
-                           port_elem);
-
-    realdev_name = smap_get(&port->cfg->other_config, "realdev");
-    realdev = iface_lookup(port->bridge, realdev_name);
-    realdev_ofp_port = realdev ? realdev->ofp_port : 0;
-
-    ofproto_port_set_realdev(ofproto, vlandev->ofp_port, realdev_ofp_port,
-                             *port->cfg->tag);
-}
-
-static struct ovsrec_port *
-synthesize_splinter_port(const char *real_dev_name,
-                         const char *vlan_dev_name, int vid)
-{
-    struct ovsrec_interface *iface;
-    struct ovsrec_port *port;
-
-    iface = xmalloc(sizeof *iface);
-    ovsrec_interface_init(iface);
-    iface->name = xstrdup(vlan_dev_name);
-    iface->type = "system";
-
-    port = xmalloc(sizeof *port);
-    ovsrec_port_init(port);
-    port->interfaces = xmemdup(&iface, sizeof iface);
-    port->n_interfaces = 1;
-    port->name = xstrdup(vlan_dev_name);
-    port->vlan_mode = "splinter";
-    port->tag = xmalloc(sizeof *port->tag);
-    *port->tag = vid;
-
-    smap_add(&port->other_config, "realdev", real_dev_name);
-
-    register_rec(port);
-    return port;
-}
-
-/* For each interface with 'br' that has VLAN splinters enabled, adds a
- * corresponding ovsrec_port to 'ports' for each splinter VLAN marked with a
- * 1-bit in the 'splinter_vlans' bitmap. */
-static void
-add_vlan_splinter_ports(struct bridge *br,
-                        const unsigned long int *splinter_vlans,
-                        struct shash *ports)
-{
-    size_t i;
-
-    /* We iterate through 'br->cfg->ports' instead of 'ports' here because
-     * we're modifying 'ports'. */
-    for (i = 0; i < br->cfg->n_ports; i++) {
-        const char *name = br->cfg->ports[i]->name;
-        struct ovsrec_port *port_cfg = shash_find_data(ports, name);
-        size_t j;
-
-        for (j = 0; j < port_cfg->n_interfaces; j++) {
-            struct ovsrec_interface *iface_cfg = port_cfg->interfaces[j];
-
-            if (vlan_splinters_is_enabled(iface_cfg)) {
-                const char *real_dev_name;
-                uint16_t vid;
-
-                real_dev_name = iface_cfg->name;
-                BITMAP_FOR_EACH_1 (vid, 4096, splinter_vlans) {
-                    const char *vlan_dev_name;
-
-                    vlan_dev_name = vlandev_get_name(real_dev_name, vid);
-                    if (vlan_dev_name
-                        && !shash_find(ports, vlan_dev_name)) {
-                        shash_add(ports, vlan_dev_name,
-                                  synthesize_splinter_port(
-                                      real_dev_name, vlan_dev_name, vid));
-                    }
-                }
-            }
-        }
-    }
-}
 
+\f
 static void
 mirror_refresh_stats(struct mirror *m)
 {
index 166f264..9080633 100644 (file)
       </column>
     </group>
 
-    <group title="VLAN Splinters">
-      <p>
-        The ``VLAN splinters'' feature increases Open vSwitch compatibility
-        with buggy network drivers in old versions of Linux that do not
-        properly support VLANs when VLAN devices are not used, at some cost
-        in memory and performance.
-      </p>
-
-      <p>
-        When VLAN splinters are enabled on a particular interface, Open vSwitch
-        creates a VLAN device for each in-use VLAN.  For sending traffic tagged
-        with a VLAN on the interface, it substitutes the VLAN device.  Traffic
-        received on the VLAN device is treated as if it had been received on
-        the interface on the particular VLAN.
-      </p>
-
-      <p>
-        VLAN splinters consider a VLAN to be in use if:
-      </p>
-
-      <ul>
-        <li>
-          The VLAN is the <ref table="Port" column="tag"/> value in any <ref
-          table="Port"/> record.
-        </li>
-
-        <li>
-          The VLAN is listed within the <ref table="Port" column="trunks"/>
-          column of the <ref table="Port"/> record of an interface on which
-          VLAN splinters are enabled.
-
-          An empty <ref table="Port" column="trunks"/> does not influence the
-          in-use VLANs: creating 4,096 VLAN devices is impractical because it
-          will exceed the current 1,024 port per datapath limit.
-        </li>
-
-        <li>
-          An OpenFlow flow within any bridge matches the VLAN.
-        </li>
-      </ul>
-
-      <p>
-        The same set of in-use VLANs applies to every interface on which VLAN
-        splinters are enabled.  That is, the set is not chosen separately for
-        each interface but selected once as the union of all in-use VLANs based
-        on the rules above.
-      </p>
-
-      <p>
-        It does not make sense to enable VLAN splinters on an interface for an
-        access port, or on an interface that is not a physical port.
-      </p>
-
-      <p>
-        VLAN splinters are deprecated.  When broken device drivers are no
-        longer in widespread use, we will delete this feature.
-      </p>
-
-      <column name="other_config" key="enable-vlan-splinters"
-              type='{"type": "boolean"}'>
-        <p>
-          Set to <code>true</code> to enable VLAN splinters on this interface.
-          Defaults to <code>false</code>.
-        </p>
-
-        <p>
-          VLAN splinters increase kernel and userspace memory overhead, so do
-          not use them unless they are needed.
-        </p>
-
-        <p>
-          VLAN splinters do not support 802.1p priority tags.  Received
-          priorities will appear to be 0, regardless of their actual values,
-          and priorities on transmitted packets will also be cleared to 0.
-        </p>
-      </column>
-    </group>
-
     <group title="Auto Attach Configuration">
       <p>
         Auto Attach configuration for a particular interface.