+++ /dev/null
-/*
- * Copyright (c) 2009, 2010, 2011 Nicira Networks.
- * Distributed under the terms of the GNU GPL version 2.
- *
- * Significant portions of this file may be copied from parts of the Linux
- * kernel, by Linus Torvalds and others.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <net/genetlink.h>
-#include "brc_procfs.h"
-#include "openvswitch/brcompat-netlink.h"
-
-/* This code implements a Generic Netlink command BRC_GENL_C_SET_PROC that can
- * be used to add, modify, and delete arbitrary files in selected
- * subdirectories of /proc. It's a horrible kluge prompted by the need to
- * simulate certain /proc/net/vlan and /proc/net/bonding files for software
- * that wants to read them, and with any luck it will go away eventually.
- *
- * The implementation is a kluge too. In particular, we want to release the
- * strings copied into the 'data' members of proc_dir_entry when the
- * proc_dir_entry structures are freed, but there doesn't appear to be a way to
- * hook that, so instead we have to rely on being the only entity modifying the
- * directories in question.
- */
-
-static int brc_seq_show(struct seq_file *seq, void *unused)
-{
- seq_puts(seq, seq->private);
- return 0;
-}
-
-static int brc_seq_open(struct inode *inode, struct file *file)
-{
- return single_open(file, brc_seq_show, PDE(inode)->data);
-}
-
-static struct file_operations brc_fops = {
- .owner = THIS_MODULE,
- .open = brc_seq_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static struct proc_dir_entry *proc_vlan_dir;
-static struct proc_dir_entry *proc_bonding_dir;
-
-static struct proc_dir_entry *brc_lookup_entry(struct proc_dir_entry *de, const char *name)
-{
- int namelen = strlen(name);
- for (de = de->subdir; de; de = de->next) {
- if (de->namelen != namelen)
- continue;
- if (!memcmp(name, de->name, de->namelen))
- return de;
- }
- return NULL;
-}
-
-static struct proc_dir_entry *brc_open_dir(const char *dir_name,
- struct proc_dir_entry *parent,
- struct proc_dir_entry **dirp)
-{
- if (!*dirp) {
- struct proc_dir_entry *dir;
- if (brc_lookup_entry(parent, dir_name)) {
- pr_warn("%s proc directory exists, can't simulate--"
- "probably its real module is loaded\n",
- dir_name);
- return NULL;
- }
- dir = *dirp = proc_mkdir(dir_name, parent);
- }
- return *dirp;
-}
-
-int brc_genl_set_proc(struct sk_buff *skb, struct genl_info *info)
-{
- struct proc_dir_entry *dir, *entry;
- const char *dir_name, *name;
- char *data;
-
- if (!info->attrs[BRC_GENL_A_PROC_DIR] ||
- VERIFY_NUL_STRING(info->attrs[BRC_GENL_A_PROC_DIR], BRC_NAME_LEN_MAX) ||
- !info->attrs[BRC_GENL_A_PROC_NAME] ||
- VERIFY_NUL_STRING(info->attrs[BRC_GENL_A_PROC_NAME], BRC_NAME_LEN_MAX) ||
- (info->attrs[BRC_GENL_A_PROC_DATA] &&
- VERIFY_NUL_STRING(info->attrs[BRC_GENL_A_PROC_DATA], INT_MAX)))
- return -EINVAL;
-
- dir_name = nla_data(info->attrs[BRC_GENL_A_PROC_DIR]);
- name = nla_data(info->attrs[BRC_GENL_A_PROC_NAME]);
-
- if (!strcmp(dir_name, "net/vlan"))
- dir = brc_open_dir("vlan", proc_net, &proc_vlan_dir);
- else if (!strcmp(dir_name, "net/bonding"))
- dir = brc_open_dir("bonding", proc_net, &proc_bonding_dir);
- else
- return -EINVAL;
- if (!dir) {
- /* Probably failed because the module that really implements
- * the function in question is loaded and already owns the
- * directory in question.*/
- return -EBUSY;
- }
-
- entry = brc_lookup_entry(dir, name);
- if (!info->attrs[BRC_GENL_A_PROC_DATA]) {
- if (!entry)
- return -ENOENT;
-
- data = entry->data;
- remove_proc_entry(name, dir);
- if (brc_lookup_entry(dir, name))
- return -EBUSY; /* Shouldn't happen */
-
- kfree(data);
- } else {
- data = kstrdup(nla_data(info->attrs[BRC_GENL_A_PROC_DATA]),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- if (entry) {
- char *old_data = entry->data;
- entry->data = data;
- kfree(old_data);
- return 0;
- }
-
- entry = create_proc_entry(name, S_IFREG|S_IRUSR|S_IWUSR, dir);
- if (!entry) {
- kfree(data);
- return -ENOBUFS;
- }
- entry->proc_fops = &brc_fops;
- entry->data = data;
- }
- return 0;
-}
-
-static void kill_proc_dir(const char *dir_name,
- struct proc_dir_entry *parent,
- struct proc_dir_entry *dir)
-{
- if (!dir)
- return;
- for (;;) {
- struct proc_dir_entry *e;
- char *data;
- char name[BRC_NAME_LEN_MAX + 1];
-
- e = dir->subdir;
- if (!e)
- break;
-
- if (e->namelen >= sizeof(name)) {
- /* Can't happen: we prevent adding names this long by
- * limiting the BRC_GENL_A_PROC_NAME string to
- * BRC_NAME_LEN_MAX bytes. */
- WARN_ON(1);
- break;
- }
- strcpy(name, e->name);
-
- data = e->data;
- e->data = NULL;
- kfree(data);
-
- remove_proc_entry(name, dir);
- }
- remove_proc_entry(dir_name, parent);
-}
-
-void brc_procfs_exit(void)
-{
- kill_proc_dir("vlan", proc_net, proc_vlan_dir);
- kill_proc_dir("bonding", proc_net, proc_bonding_dir);
-}
+++ /dev/null
-/*
- * Copyright (c) 2009, 2011 Nicira Networks.
- * Distributed under the terms of the GNU GPL version 2.
- *
- * Significant portions of this file may be copied from parts of the Linux
- * kernel, by Linus Torvalds and others.
- */
-
-#ifndef BRC_PROCFS_H
-#define BRC_PROCFS_H 1
-
-struct sk_buff;
-struct genl_info;
-
-/* Maximum length of BRC_GENL_A_PROC_DIR and BRC_GENL_A_PROC_NAME strings. */
-#define BRC_NAME_LEN_MAX 32
-
-void brc_procfs_exit(void);
-int brc_genl_set_proc(struct sk_buff *skb, struct genl_info *info);
-
-#endif /* brc_procfs.h */
-
#include <net/genetlink.h>
#include "openvswitch/brcompat-netlink.h"
-#include "brc_procfs.h"
#include "datapath.h"
static struct genl_family brc_genl_family;
/* Attribute policy: what each attribute may contain. */
static struct nla_policy brc_genl_policy[BRC_GENL_A_MAX + 1] = {
[BRC_GENL_A_ERR_CODE] = { .type = NLA_U32 },
-
-#ifdef HAVE_NLA_NUL_STRING
- [BRC_GENL_A_PROC_DIR] = { .type = NLA_NUL_STRING,
- .len = BRC_NAME_LEN_MAX },
- [BRC_GENL_A_PROC_NAME] = { .type = NLA_NUL_STRING,
- .len = BRC_NAME_LEN_MAX },
- [BRC_GENL_A_PROC_DATA] = { .type = NLA_NUL_STRING },
-#endif
-
[BRC_GENL_A_FDB_DATA] = { .type = NLA_UNSPEC },
};
.policy = brc_genl_policy,
.doit = brc_genl_dp_result,
},
- { .cmd = BRC_GENL_C_SET_PROC,
- .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
- .policy = brc_genl_policy,
- .doit = brc_genl_set_proc,
- },
};
static struct sk_buff *brc_send_command(struct sk_buff *request,
brioctl_set(NULL);
genl_unregister_family(&brc_genl_family);
- brc_procfs_exit();
}
module_init(brc_init);
/Module.markers
/actions.c
/addrconf_core-openvswitch.c
-/brc_procfs.c
/brc_sysfs_dp.c
/brc_sysfs_if.c
/brcompat.c
linux-2.6/compat-2.6/genetlink.inc
both_modules += brcompat
-brcompat_sources = \
- linux-2.6/compat-2.6/genetlink-brcompat.c \
- brcompat.c \
- brc_procfs.c
-brcompat_headers = \
- brc_procfs.h
+brcompat_sources = linux-2.6/compat-2.6/genetlink-brcompat.c brcompat.c
+brcompat_headers =
/*
- * Copyright (c) 2008, 2009 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2011 Nicira Networks.
*
* This file is offered under your choice of two licenses: Apache 2.0 or GNU
* GPL 2.0 or later. The permission statements for each of these licenses is
/* BRC_GENL_C_QUERY_MC. */
BRC_GENL_A_MC_GROUP, /* K: Generic netlink multicast group. */
- /* BRC_GENL_C_SET_PROC. */
- BRC_GENL_A_PROC_DIR, /* U: Name of subdirectory in /proc. */
- BRC_GENL_A_PROC_NAME, /* U: Name of file in /proc. */
- BRC_GENL_A_PROC_DATA, /* U: Contents of file in /proc. */
-
/* BRC_GENL_C_FDB_QUERY. */
BRC_GENL_A_FDB_COUNT, /* K: Number of FDB entries to read. */
BRC_GENL_A_FDB_SKIP, /* K: Record offset into FDB to start reading. */
BRC_GENL_C_PORT_ADD, /* K: Port added to datapath. */
BRC_GENL_C_PORT_DEL, /* K: Port removed from datapath. */
BRC_GENL_C_QUERY_MC, /* U: Get multicast group for brcompat. */
- BRC_GENL_C_SET_PROC, /* U: Set contents of file in /proc. */
BRC_GENL_C_FDB_QUERY, /* K: Read records from forwarding database. */
BRC_GENL_C_GET_BRIDGES, /* K: Get ifindexes of all bridges. */
BRC_GENL_C_GET_PORTS, /* K: Get ifindexes of all ports on a bridge. */
vswitchd_ovs_vswitchd_SOURCES = \
vswitchd/bridge.c \
vswitchd/bridge.h \
- vswitchd/proc-net-compat.c \
- vswitchd/proc-net-compat.h \
vswitchd/ovs-vswitchd.c \
vswitchd/system-stats.c \
vswitchd/system-stats.h \
#include "ovsdb-data.h"
#include "packets.h"
#include "poll-loop.h"
-#include "proc-net-compat.h"
#include "process.h"
#include "sha1.h"
#include "shash.h"
tag_type active_iface_tag; /* Tag for bcast flows. */
tag_type no_ifaces_tag; /* Tag for flows when all ifaces disabled. */
int updelay, downdelay; /* Delay before iface goes up/down, in ms. */
- bool bond_compat_is_stale; /* Need to call port_update_bond_compat()? */
bool bond_fake_iface; /* Fake a bond interface for legacy compat? */
bool miimon; /* Use miimon instead of carrier? */
long long int bond_miimon_interval; /* Miimon status refresh interval. */
static struct iface *port_lookup_iface(const struct port *, const char *name);
static struct port *port_from_dp_ifidx(const struct bridge *,
uint16_t dp_ifidx);
-static void port_update_bond_compat(struct port *);
-static void port_update_vlan_compat(struct port *);
static void port_update_bonding(struct port *);
static void port_update_lacp(struct port *);
struct port *port = br->ports[i];
int j;
- port_update_vlan_compat(port);
port_update_bonding(port);
port_update_lacp(port);
return false;
}
e->iface_tag = tag_create_random();
- ((struct port *) port)->bond_compat_is_stale = true;
}
*tags |= e->iface_tag;
iface = port->ifaces[e->iface_idx];
}
moving_active_iface = false;
- port->bond_compat_is_stale = true;
}
/* Attempts to make the sum of the bond slaves' statistics appear on the fake
iface->up = carrier;
iface->lacp_tx = 0;
- iface->port->bond_compat_is_stale = true;
}
static void
port->bond_next_fake_iface_update = time_msec() + 1000;
}
}
-
- if (port->bond_compat_is_stale) {
- port->bond_compat_is_stale = false;
- port_update_bond_compat(port);
- }
}
}
}
if (i < from->n_hashes) {
bond_shift_load(from, to, i);
- port->bond_compat_is_stale = true;
/* If the result of the migration changed the relative order of
* 'from' and 'to' swap them back to maintain invariants. */
ofproto_revalidate(port->bridge->ofproto, entry->iface_tag);
entry->iface_idx = iface->port_ifidx;
entry->iface_tag = tag_create_random();
- port->bond_compat_is_stale = true;
unixctl_command_reply(conn, 200, "migrated");
}
struct port *del;
int i;
- proc_net_compat_update_vlan(port->name, NULL, 0);
- proc_net_compat_update_bond(port->name, NULL);
-
for (i = 0; i < MAX_MIRRORS; i++) {
struct mirror *m = br->mirrors[i];
if (m && m->out_port == port) {
}
if (port->n_ifaces < 2) {
/* Not a bonded port. */
- if (port->bond_hash) {
- free(port->bond_hash);
- port->bond_hash = NULL;
- port->bond_compat_is_stale = true;
- }
-
+ free(port->bond_hash);
+ port->bond_hash = NULL;
port->bond_fake_iface = false;
} else {
size_t i;
free(port->bond_hash);
port->bond_hash = NULL;
}
- port->bond_compat_is_stale = true;
port->bond_fake_iface = port->cfg->bond_fake_iface;
if (!port->miimon) {
}
}
}
-
-static void
-port_update_bond_compat(struct port *port)
-{
- struct compat_bond_hash compat_hashes[BOND_MASK + 1];
- struct compat_bond bond;
- size_t i;
-
- if (port->n_ifaces < 2 || port->bond_mode != BM_SLB) {
- proc_net_compat_update_bond(port->name, NULL);
- return;
- }
-
- bond.up = false;
- bond.updelay = port->updelay;
- bond.downdelay = port->downdelay;
-
- bond.n_hashes = 0;
- bond.hashes = compat_hashes;
- if (port->bond_hash) {
- const struct bond_entry *e;
- for (e = port->bond_hash; e <= &port->bond_hash[BOND_MASK]; e++) {
- if (e->iface_idx >= 0 && e->iface_idx < port->n_ifaces) {
- struct compat_bond_hash *cbh = &bond.hashes[bond.n_hashes++];
- cbh->hash = e - port->bond_hash;
- cbh->netdev_name = port->ifaces[e->iface_idx]->name;
- }
- }
- }
-
- bond.n_slaves = port->n_ifaces;
- bond.slaves = xmalloc(port->n_ifaces * sizeof *bond.slaves);
- for (i = 0; i < port->n_ifaces; i++) {
- struct iface *iface = port->ifaces[i];
- struct compat_bond_slave *slave = &bond.slaves[i];
- slave->name = iface->name;
-
- /* We need to make the same determination as the Linux bonding
- * code to determine whether a slave should be consider "up".
- * The Linux function bond_miimon_inspect() supports four
- * BOND_LINK_* states:
- *
- * - BOND_LINK_UP: carrier detected, updelay has passed.
- * - BOND_LINK_FAIL: carrier lost, downdelay in progress.
- * - BOND_LINK_DOWN: carrier lost, downdelay has passed.
- * - BOND_LINK_BACK: carrier detected, updelay in progress.
- *
- * The function bond_info_show_slave() only considers BOND_LINK_UP
- * to be "up" and anything else to be "down".
- */
- slave->up = iface->enabled && iface->delay_expires == LLONG_MAX;
- if (slave->up) {
- bond.up = true;
- }
- netdev_get_etheraddr(iface->netdev, slave->mac);
- }
-
- if (port->bond_fake_iface) {
- struct netdev *bond_netdev;
-
- if (!netdev_open_default(port->name, &bond_netdev)) {
- if (bond.up) {
- netdev_turn_flags_on(bond_netdev, NETDEV_UP, true);
- } else {
- netdev_turn_flags_off(bond_netdev, NETDEV_UP, true);
- }
- netdev_close(bond_netdev);
- }
- }
-
- proc_net_compat_update_bond(port->name, &bond);
- free(bond.slaves);
-}
-
-static void
-port_update_vlan_compat(struct port *port)
-{
- struct bridge *br = port->bridge;
- char *vlandev_name = NULL;
-
- if (port->vlan > 0) {
- /* Figure out the name that the VLAN device should actually have, if it
- * existed. This takes some work because the VLAN device would not
- * have port->name in its name; rather, it would have the trunk port's
- * name, and 'port' would be attached to a bridge that also had the
- * VLAN device one of its ports. So we need to find a trunk port that
- * includes port->vlan.
- *
- * There might be more than one candidate. This doesn't happen on
- * XenServer, so if it happens we just pick the first choice in
- * alphabetical order instead of creating multiple VLAN devices. */
- size_t i;
- for (i = 0; i < br->n_ports; i++) {
- struct port *p = br->ports[i];
- if (port_trunks_vlan(p, port->vlan)
- && p->n_ifaces
- && (!vlandev_name || strcmp(p->name, vlandev_name) <= 0))
- {
- uint8_t ea[ETH_ADDR_LEN];
- netdev_get_etheraddr(p->ifaces[0]->netdev, ea);
- if (!eth_addr_is_multicast(ea) &&
- !eth_addr_is_reserved(ea) &&
- !eth_addr_is_zero(ea)) {
- vlandev_name = p->name;
- }
- }
- }
- }
- proc_net_compat_update_vlan(port->name, vlandev_name, port->vlan);
-}
\f
/* Interface functions. */
\fBovs\-vswitchd\fR emits a log message if \fBmlockall()\fR is
unavailable or unsuccessful.
.
-.IP "\fB\-\-fake\-proc\-net\fR"
-Causes \fBovs\-vswitchd\fR to simulate some files in \fB/proc/net/vlan\fR
-and \fB/proc/net/bonding\fR that some legacy software expects to
-exist. This option should only be used if such legacy software is
-actually in use. It requires the \fBbrcompat_mod.ko\fR kernel module
-to be loaded.
-.IP
-On non-Linux hosts, this option is accepted but has no effect.
-.
.ds DD \
\fBovs\-vswitchd\fR detaches only after it has connected to the \
database, retrieved the initial configuration, and set up that \
#include "netdev.h"
#include "ovsdb-idl.h"
#include "poll-loop.h"
-#include "proc-net-compat.h"
#include "process.h"
#include "signals.h"
#include "stream-ssl.h"
enum {
OPT_PEER_CA_CERT = UCHAR_MAX + 1,
OPT_MLOCKALL,
- OPT_FAKE_PROC_NET,
VLOG_OPTION_ENUMS,
LEAK_CHECKER_OPTION_ENUMS,
OPT_BOOTSTRAP_CA_CERT,
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"mlockall", no_argument, 0, OPT_MLOCKALL},
- {"fake-proc-net", no_argument, 0, OPT_FAKE_PROC_NET},
DAEMON_LONG_OPTIONS,
VLOG_LONG_OPTIONS,
LEAK_CHECKER_LONG_OPTIONS,
{0, 0, 0, 0},
};
char *short_options = long_options_to_short_options(long_options);
- int error;
for (;;) {
int c;
#endif
break;
- case OPT_FAKE_PROC_NET:
- error = proc_net_compat_init();
- if (error) {
- ovs_fatal(error, "failed to initialize /proc/net "
- "compatibility");
- }
- break;
-
VLOG_OPTION_HANDLERS
DAEMON_OPTION_HANDLERS
LEAK_CHECKER_OPTION_HANDLERS
stream_usage("DATABASE", true, false, true);
daemon_usage();
vlog_usage();
- printf("\nLegacy compatibility options:\n"
- " --fake-proc-net simulate some files in /proc/net\n"
- "\nOther options:\n"
+ printf("\nOther options:\n"
" -h, --help display this help message\n"
" -V, --version display version information\n");
leak_checker_usage();
+++ /dev/null
-/* Copyright (c) 2009, 2010, 2011 Nicira Networks
- *
- * 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 "proc-net-compat.h"
-
-#ifdef HAVE_NETLINK
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <string.h>
-#include "dynamic-string.h"
-#include "hash.h"
-#include "netlink-protocol.h"
-#include "netlink-socket.h"
-#include "netlink.h"
-#include "ofpbuf.h"
-#include "openvswitch/brcompat-netlink.h"
-#include "hmap.h"
-#include "shash.h"
-#include "svec.h"
-#include "vlog.h"
-
-VLOG_DEFINE_THIS_MODULE(proc_net_compat);
-
-/* Netlink socket to bridge compatibility kernel module. */
-static struct nl_sock *brc_sock;
-
-/* The Generic Netlink family number used for bridge compatibility. */
-static int brc_family = 0;
-
-/* Rate limiting for log messages. */
-static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
-
-static void flush_dir(const char *dir);
-static int set_proc_file(const char *dir, const char *file, const char *data);
-
-/* Initializes the /proc/net compatibility layer. Returns 0 if successful,
- * otherwise a positive errno value. */
-int
-proc_net_compat_init(void)
-{
- if (!brc_sock) {
- int retval = nl_lookup_genl_family(BRC_GENL_FAMILY_NAME, &brc_family);
- if (retval) {
- return retval;
- }
-
- retval = nl_sock_create(NETLINK_GENERIC, &brc_sock);
- if (retval) {
- return retval;
- }
-
- flush_dir("/proc/net/vlan");
- flush_dir("/proc/net/bonding");
- }
- return 0;
-}
-
-static int
-set_proc_file(const char *dir, const char *file, const char *data)
-{
- struct ofpbuf request;
- int retval;
-
- ofpbuf_init(&request, 0);
- nl_msg_put_genlmsghdr(&request, 1024, brc_family, NLM_F_REQUEST,
- BRC_GENL_C_SET_PROC, 1);
- nl_msg_put_string(&request, BRC_GENL_A_PROC_DIR, dir);
- nl_msg_put_string(&request, BRC_GENL_A_PROC_NAME, file);
- if (data) {
- nl_msg_put_string(&request, BRC_GENL_A_PROC_DATA, data);
- }
-
- retval = nl_sock_transact(brc_sock, &request, NULL);
- ofpbuf_uninit(&request);
- if (retval) {
- VLOG_WARN_RL(&rl, "failed to %s /proc/%s/%s (%s)",
- data ? "update" : "remove", dir, file, strerror(retval));
- }
- return retval;
-}
-
-static void
-flush_dir(const char *dir)
-{
- const char *subdir;
- struct dirent *de;
- DIR *stream;
-
- assert(!memcmp(dir, "/proc/", 6));
- subdir = dir + 6;
-
- stream = opendir(dir);
- if (!stream) {
- if (errno != ENOENT) {
- VLOG_WARN_RL(&rl, "%s: open failed (%s)", dir, strerror(errno));
- }
- return;
- }
-
- while ((de = readdir(stream)) != NULL) {
- if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {
- set_proc_file(subdir, de->d_name, NULL);
- }
- }
- closedir(stream);
-}
-\f
-/* If 'bond' is nonnull, creates a file in /proc/net/bonding for a bond with
- * the given 'name' and the details in 'bond'. If 'bond' is null, deletes
- * the /proc/net/bonding file with the given 'name'.
- *
- * This function has no effect unless proc_net_compat_init() has been
- * called. */
-void
-proc_net_compat_update_bond(const char *name, const struct compat_bond *bond)
-{
- struct ds ds;
- int i;
-
- if (!brc_sock) {
- return;
- }
-
- if (!bond) {
- set_proc_file("net/bonding", name, NULL);
- return;
- }
-
- ds_init(&ds);
- ds_put_format(
- &ds,
- "Ethernet Channel Bonding Driver: ovs-vswitchd "
- VERSION BUILDNR" ("__DATE__" "__TIME__")\n"
- "Bonding Mode: source load balancing\n"
- "Primary Slave: None\n"
- "Currently Active Slave: None\n"
- "MII Status: %s\n"
- "MII Polling Interval (ms): 100\n"
- "Up Delay (ms): %d\n"
- "Down Delay (ms): %d\n"
- "\n"
- "Source load balancing info:\n",
- bond->up ? "up" : "down", bond->updelay, bond->downdelay);
-
- for (i = 0; i < bond->n_hashes; i++) {
- const struct compat_bond_hash *cbh = &bond->hashes[i];
- ds_put_format(&ds, " [%03d] = %s\n", cbh->hash, cbh->netdev_name);
- }
-
- for (i = 0; i < bond->n_slaves; i++) {
- const struct compat_bond_slave *slave = &bond->slaves[i];
- ds_put_format(
- &ds,
- "\n"
- "Slave Interface: %s\n"
- "MII Status: %s\n"
- "Link Failure Count: 0\n"
- "Permanent HW addr: "ETH_ADDR_FMT"\n",
- slave->name, slave->up ? "up" : "down",
- ETH_ADDR_ARGS(slave->mac));
- }
- set_proc_file("net/bonding", name, ds_cstr(&ds));
- ds_destroy(&ds);
-}
-\f
-/* /proc/net/vlan compatibility.
- *
- * This is much more complex than I expected it to be. */
-
-struct compat_vlan {
- /* Hash key. */
- struct hmap_node trunk_node; /* Hash map node. */
- char *trunk_dev; /* Name of trunk network device. */
- int vid; /* VLAN number. */
-
- /* Auxiliary data. */
- char *vlan_dev; /* sprintf("%s.%d", trunk_dev, vid); */
- struct svec tagged_devs; /* Name of tagged network device(s). */
-};
-
-/* Current set of VLAN devices, indexed two different ways. */
-static struct hmap vlans_by_trunk = HMAP_INITIALIZER(&vlans_by_trunk);
-static struct shash vlans_by_tagged = SHASH_INITIALIZER(&vlans_by_tagged);
-
-static bool remove_tagged_dev(struct shash_node *, const char *tagged_dev);
-static void update_vlan_config(void);
-static void set_vlan_proc_file(const struct compat_vlan *);
-static uint32_t hash_vlan(const char *trunk_dev, uint32_t vid);
-
-/* Updates the /proc/net/vlan compatibility layer's idea of what trunk device
- * and VLAN the given 'tagged_dev' is associated with. If 'tagged_dev' has an
- * implicit VLAN tag, then 'trunk_dev' should be the name of a network device
- * on the same bridge that trunks that VLAN, and 'vid' should be the VLAN tag
- * number. If 'tagged_dev' does not have an implicit VLAN tag, then
- * 'trunk_dev' should be NULL and 'vid' should be -1.
- *
- * This function has no effect unless proc_net_compat_init() has been
- * called. */
-void
-proc_net_compat_update_vlan(const char *tagged_dev, const char *trunk_dev,
- int vid)
-{
- struct compat_vlan *vlan;
- struct shash_node *node;
-
- if (!brc_sock) {
- return;
- }
-
- /* Find the compat_vlan that we currently have for 'tagged_dev' (if
- * any). */
- node = shash_find(&vlans_by_tagged, tagged_dev);
- vlan = node ? node->data : NULL;
- if (vid <= 0 || !trunk_dev) {
- if (vlan) {
- if (remove_tagged_dev(node, tagged_dev)) {
- update_vlan_config();
- }
- }
- } else {
- if (vlan) {
- if (!strcmp(trunk_dev, vlan->trunk_dev) && vid == vlan->vid) {
- /* No change. */
- return;
- } else {
- /* 'tagged_dev' is attached to the wrong compat_vlan. Start
- * by removing it from that one. */
- remove_tagged_dev(node, tagged_dev);
- node = NULL;
- vlan = NULL;
- }
- }
-
- /* 'tagged_dev' is not attached to any compat_vlan. Find the
- * compat_vlan corresponding to (trunk_dev,vid) to attach it to, or
- * create a new compat_vlan if none exists for (trunk_dev,vid). */
- HMAP_FOR_EACH_WITH_HASH (vlan, trunk_node, hash_vlan(trunk_dev, vid),
- &vlans_by_trunk) {
- if (!strcmp(trunk_dev, vlan->trunk_dev) && vid == vlan->vid) {
- break;
- }
- }
- if (!vlan) {
- /* Create a new compat_vlan for (trunk_dev,vid). */
- vlan = xzalloc(sizeof *vlan);
- vlan->trunk_dev = xstrdup(trunk_dev);
- vlan->vid = vid;
- vlan->vlan_dev = xasprintf("%s.%d", trunk_dev, vid);
- svec_init(&vlan->tagged_devs);
- hmap_insert(&vlans_by_trunk, &vlan->trunk_node,
- hash_vlan(trunk_dev, vid));
- set_vlan_proc_file(vlan);
- }
-
- /* Attach 'tagged_dev' to 'vlan'. */
- svec_add(&vlan->tagged_devs, tagged_dev);
- shash_add(&vlans_by_tagged, tagged_dev, vlan);
- svec_sort(&vlan->tagged_devs);
- update_vlan_config();
- }
-}
-
-/* Remove 'tagged_dev' from the compat_vlan in 'node'. If that causes the
- * compat_vlan to have no tagged_devs left, destroy the compat_vlan too. */
-static bool
-remove_tagged_dev(struct shash_node *node, const char *tagged_dev)
-{
- struct compat_vlan *vlan = node->data;
-
- svec_del(&vlan->tagged_devs, tagged_dev);
- shash_delete(&vlans_by_tagged, node);
- if (!vlan->tagged_devs.n) {
- set_proc_file("net/vlan", vlan->vlan_dev, NULL);
-
- hmap_remove(&vlans_by_trunk, &vlan->trunk_node);
- svec_destroy(&vlan->tagged_devs);
- free(vlan->trunk_dev);
- free(vlan->vlan_dev);
- free(vlan);
- return true;
- }
- return false;
-}
-
-/* Returns a hash value for (trunk_dev,vid). */
-static uint32_t
-hash_vlan(const char *trunk_dev, uint32_t vid)
-{
- return hash_int(vid, hash_string(trunk_dev, 0));
-}
-
-/* Update /proc/net/vlan/<vlan_dev> for 'vlan'. */
-static void
-set_vlan_proc_file(const struct compat_vlan *vlan)
-{
- struct ds ds;
-
- ds_init(&ds);
- ds_put_format(
- &ds,
- "%s VID: %d\t REORDER_HDR: 1 dev->priv_flags: 81\n"
- " total frames received 0\n"
- " total bytes received 0\n"
- " Broadcast/Multicast Rcvd 0\n"
- "\n"
- " total frames transmitted 0\n"
- " total bytes transmitted 0\n"
- " total headroom inc 0\n"
- " total encap on xmit 0\n"
- "Device: %s\n"
- "INGRESS priority mappings: 0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0\n"
- "EGRESSS priority Mappings: \n",
- vlan->vlan_dev, vlan->vid, vlan->trunk_dev);
- set_proc_file("net/vlan", vlan->vlan_dev, ds_cstr(&ds));
- ds_destroy(&ds);
-}
-
-/* Update /proc/net/vlan/config. */
-static void
-update_vlan_config(void)
-{
- struct compat_vlan *vlan;
- struct ds ds;
-
- ds_init(&ds);
- ds_put_cstr(&ds, "VLAN Dev name | VLAN ID\n"
- "Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD\n");
- HMAP_FOR_EACH (vlan, trunk_node, &vlans_by_trunk) {
- ds_put_format(&ds, "%-15s| %d | %s\n",
- vlan->vlan_dev, vlan->vid, vlan->trunk_dev);
- }
- set_proc_file("net/vlan", "config", ds_cstr(&ds));
- ds_destroy(&ds);
-}
-#else /* !HAVE_NETLINK */
-#include "compiler.h"
-
-int
-proc_net_compat_init(void)
-{
- return 0;
-}
-
-void
-proc_net_compat_update_bond(const char *name OVS_UNUSED,
- const struct compat_bond *bond OVS_UNUSED)
-{
-}
-
-void
-proc_net_compat_update_vlan(const char *tagged_dev OVS_UNUSED,
- const char *trunk_dev OVS_UNUSED,
- int vid OVS_UNUSED)
-{
-}
-#endif /* !HAVE_NETLINK */
+++ /dev/null
-/* Copyright (c) 2009 Nicira Networks
- *
- * 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 VSWITCHD_PROC_NET_COMPAT_H
-#define VSWITCHD_PROC_NET_COMPAT_H 1
-
-#include "packets.h"
-
-struct compat_bond {
- bool up;
- int updelay;
- int downdelay;
-
- int n_hashes;
- struct compat_bond_hash *hashes;
-
- int n_slaves;
- struct compat_bond_slave *slaves;
-};
-
-struct compat_bond_hash {
- int hash;
- const char *netdev_name;
-};
-
-struct compat_bond_slave {
- const char *name;
- bool up;
- uint8_t mac[ETH_ADDR_LEN];
-};
-
-int proc_net_compat_init(void);
-void proc_net_compat_update_bond(const char *name, const struct compat_bond *);
-void proc_net_compat_update_vlan(const char *dev, const char *vlandev,
- int vlan);
-
-#endif /* vswitchd/proc-net-compat.h */