X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=3b7ec51f44fee1ae14326184d4d46b5e38143fe6;hb=bb60fa749da7f725f2f000a90ea317ad4b1383d2;hp=5494dea35c9aca3195fc44d653a63c27fbd55501;hpb=d17ee8689bff22541dccaa792b70a848641f3646;p=openvswitch diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 5494dea3..3b7ec51f 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -50,6 +50,7 @@ #include "port-array.h" #include "proc-net-compat.h" #include "process.h" +#include "shash.h" #include "socket-util.h" #include "stp.h" #include "svec.h" @@ -60,6 +61,7 @@ #include "vconn-ssl.h" #include "xenserver.h" #include "xtoxll.h" +#include "sflow_api.h" #define THIS_MODULE VLM_bridge #include "vlog.h" @@ -209,6 +211,7 @@ static uint64_t bridge_pick_datapath_id(struct bridge *, const uint8_t bridge_ea[ETH_ADDR_LEN], struct iface *hw_addr_iface); static struct iface *bridge_get_local_iface(struct bridge *); +static const char *bridge_get_controller(const struct bridge *br); static uint64_t dpid_from_hash(const void *, size_t nbytes); static void bridge_unixctl_fdb_show(struct unixctl_conn *, const char *args); @@ -369,6 +372,70 @@ bridge_configure_ssl(void) } #endif +/* Attempt to create the network device 'iface_name' through the netdev + * library. */ +static int +set_up_iface(const char *iface_name, bool create) +{ + const char *type; + const char *arg; + struct svec arg_svec; + struct shash args; + int error; + size_t i; + + /* If a type is not explicitly declared, then assume it's an existing + * "system" device. */ + type = cfg_get_string(0, "iface.%s.type", iface_name); + if (!type || !strcmp(type, "system")) { + return 0; + } + + svec_init(&arg_svec); + cfg_get_subsections(&arg_svec, "iface.%s.args", iface_name); + + shash_init(&args); + SVEC_FOR_EACH (i, arg, &arg_svec) { + const char *value; + + value = cfg_get_string(0, "iface.%s.args.%s", iface_name, arg); + if (value) { + shash_add(&args, arg, xstrdup(value)); + } + } + + if (create) { + error = netdev_create(iface_name, type, &args); + } else { + /* xxx Check to make sure that the type hasn't changed. */ + error = netdev_reconfigure(iface_name, &args); + } + + svec_destroy(&arg_svec); + shash_destroy(&args); + + return error; +} + +static int +create_iface(const char *iface_name) +{ + return set_up_iface(iface_name, true); +} + +static int +reconfigure_iface(const char *iface_name) +{ + return set_up_iface(iface_name, false); +} + +static void +destroy_iface(const char *iface_name) +{ + netdev_destroy(iface_name); +} + + /* iterate_and_prune_ifaces() callback function that opens the network device * for 'iface', if it is not already open, and retrieves the interface's MAC * address and carrier status. */ @@ -462,6 +529,7 @@ bridge_reconfigure(void) struct svec old_br, new_br; struct bridge *br, *next; size_t i; + int sflow_bridge_number; COVERAGE_INC(bridge_reconfigure); @@ -524,6 +592,7 @@ bridge_reconfigure(void) p->devname, dpif_name(br->dpif), strerror(retval)); } + destroy_iface(p->devname); } } svec_destroy(&want_ifaces); @@ -544,11 +613,25 @@ bridge_reconfigure(void) bridge_get_all_ifaces(br, &want_ifaces); svec_diff(&want_ifaces, &cur_ifaces, &add_ifaces, NULL, NULL); + for (i = 0; i < cur_ifaces.n; i++) { + const char *if_name = cur_ifaces.names[i]; + reconfigure_iface(if_name); + } + for (i = 0; i < add_ifaces.n; i++) { const char *if_name = add_ifaces.names[i]; bool internal; int error; + /* Attempt to create the network interface in case it + * doesn't exist yet. */ + error = create_iface(if_name); + if (error) { + VLOG_WARN("could not create iface %s: %s\n", if_name, + strerror(error)); + continue; + } + /* Add to datapath. */ internal = iface_is_internal(br, if_name); error = dpif_port_add(br->dpif, if_name, @@ -566,6 +649,7 @@ bridge_reconfigure(void) svec_destroy(&want_ifaces); svec_destroy(&add_ifaces); } + sflow_bridge_number = 0; LIST_FOR_EACH (br, struct bridge, node, &all_bridges) { uint8_t ea[8]; uint64_t dpid; @@ -636,6 +720,42 @@ bridge_reconfigure(void) } svec_destroy(&nf_options.collectors); + if (cfg_has("sflow.%s.host", br->name)) { + struct ofproto_sflow_options oso; + + svec_init(&oso.targets); + cfg_get_all_keys(&oso.targets, "sflow.%s.host", br->name); + + oso.sampling_rate = SFL_DEFAULT_SAMPLING_RATE; + if (cfg_has("sflow.%s.sampling", br->name)) { + oso.sampling_rate = cfg_get_int(0, "sflow.%s.sampling", + br->name); + } + + oso.polling_interval = SFL_DEFAULT_POLLING_INTERVAL; + if (cfg_has("sflow.%s.polling", br->name)) { + oso.polling_interval = cfg_get_int(0, "sflow.%s.polling", + br->name); + } + + oso.header_len = SFL_DEFAULT_HEADER_SIZE; + if (cfg_has("sflow.%s.header", br->name)) { + oso.header_len = cfg_get_int(0, "sflow.%s.header", br->name); + } + + oso.sub_id = sflow_bridge_number++; + oso.agent_device = (char *) cfg_get_string(0, "sflow.%s.agent", + br->name); + oso.control_ip = (char *) cfg_get_string(0, + "bridge.%s.controller.ip", + br->name); + ofproto_set_sflow(br->ofproto, &oso); + + svec_destroy(&oso.targets); + } else { + ofproto_set_sflow(br->ofproto, NULL); + } + /* Update the controller and related settings. It would be more * straightforward to call this from bridge_reconfigure_one(), but we * can't do it there for two reasons. First, and most importantly, at @@ -968,21 +1088,12 @@ bridge_create(const char *name) assert(!bridge_lookup(name)); br = xcalloc(1, sizeof *br); - error = dpif_create(name, &br->dpif); - if (error == EEXIST || error == EBUSY) { - error = dpif_open(name, &br->dpif); - if (error) { - VLOG_ERR("datapath %s already exists but cannot be opened: %s", - name, strerror(error)); - free(br); - return NULL; - } - dpif_flow_flush(br->dpif); - } else if (error) { - VLOG_ERR("failed to create datapath %s: %s", name, strerror(error)); + error = dpif_create_and_open(name, &br->dpif); + if (error) { free(br); return NULL; } + dpif_flow_flush(br->dpif); error = ofproto_create(name, &bridge_ofhooks, br, &br->ofproto); if (error) {