X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=dd3099f84ede808ae3bb48f47877cac9bc641e64;hb=ea7655d9f9d38a3af7250de8ba0b89115b5f4a5e;hp=06d6366f23a8bf162c6b102b45e0001cce2744f6;hpb=ee4dd8eb947b13dfc76f7898e9929d58b48ce03c;p=sliver-openvswitch.git diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 06d6366f2..dd3099f84 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. +/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ #include #include "bridge.h" -#include #include #include #include @@ -182,10 +181,11 @@ static void bridge_configure_datapath_id(struct bridge *); static void bridge_configure_flow_eviction_threshold(struct bridge *); static void bridge_configure_netflow(struct bridge *); static void bridge_configure_forward_bpdu(struct bridge *); -static void bridge_configure_mac_idle_time(struct bridge *); +static void bridge_configure_mac_table(struct bridge *); static void bridge_configure_sflow(struct bridge *, int *sflow_bridge_number); static void bridge_configure_stp(struct bridge *); static void bridge_configure_tables(struct bridge *); +static void bridge_configure_dp_desc(struct bridge *); static void bridge_configure_remotes(struct bridge *, const struct sockaddr_in *managers, size_t n_managers); @@ -247,6 +247,7 @@ static void iface_refresh_cfm_stats(struct iface *); static void iface_refresh_stats(struct iface *); static void iface_refresh_status(struct iface *); static bool iface_is_synthetic(const struct iface *); +static int64_t iface_pick_ofport(const struct ovsrec_interface *); /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * @@ -295,8 +296,7 @@ bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg) iface_hint = xmalloc(sizeof *iface_hint); iface_hint->br_name = br_cfg->name; iface_hint->br_type = br_cfg->datapath_type; - iface_hint->ofp_port = if_cfg->n_ofport_request ? - *if_cfg->ofport_request : OFPP_NONE; + iface_hint->ofp_port = iface_pick_ofport(if_cfg); shash_add(&iface_hints, if_cfg->name, iface_hint); } @@ -470,7 +470,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) COVERAGE_INC(bridge_reconfigure); - assert(!reconfiguring); + ovs_assert(!reconfiguring); reconfiguring = true; /* Destroy "struct bridge"s, "struct port"s, and "struct iface"s according @@ -564,7 +564,7 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg) struct bridge *br; bool done; - assert(reconfiguring); + ovs_assert(reconfiguring); done = bridge_reconfigure_ofp(); /* Complete the configuration. */ @@ -591,12 +591,13 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg) bridge_configure_mirrors(br); bridge_configure_flow_eviction_threshold(br); bridge_configure_forward_bpdu(br); - bridge_configure_mac_idle_time(br); + bridge_configure_mac_table(br); bridge_configure_remotes(br, managers, n_managers); bridge_configure_netflow(br); bridge_configure_sflow(br, &sflow_bridge_number); bridge_configure_stp(br); bridge_configure_tables(br); + bridge_configure_dp_desc(br); } free(managers); @@ -606,7 +607,7 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg) daemonize_complete(); reconfiguring = false; - VLOG_INFO("%s (Open vSwitch) %s", program_name, VERSION); + VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION); } return done; @@ -1186,7 +1187,7 @@ iface_set_ofp_port(struct iface *iface, int ofp_port) { struct bridge *br = iface->port->bridge; - assert(iface->ofp_port < 0 && ofp_port >= 0); + ovs_assert(iface->ofp_port < 0 && ofp_port >= 0); iface->ofp_port = ofp_port; hmap_insert(&br->ifaces, &iface->ofp_port_node, hash_int(ofp_port, 0)); iface_set_ofport(iface->cfg, ofp_port); @@ -1400,10 +1401,11 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) * internal datastructures may not be consistent. Eventually, when port * additions and deletions are cheaper, these calls should be removed. */ bridge_run_fast(); - assert(!iface_lookup(br, iface_cfg->name)); + ovs_assert(!iface_lookup(br, iface_cfg->name)); error = iface_do_create(br, if_cfg, &ofp_port, &netdev); bridge_run_fast(); if (error) { + iface_set_ofport(iface_cfg, -1); iface_clear_db_record(iface_cfg); ok = false; goto done; @@ -1492,18 +1494,27 @@ bridge_configure_forward_bpdu(struct bridge *br) false)); } -/* Set MAC aging time for 'br'. */ +/* Set MAC learning table configuration for 'br'. */ static void -bridge_configure_mac_idle_time(struct bridge *br) +bridge_configure_mac_table(struct bridge *br) { const char *idle_time_str; int idle_time; + const char *mac_table_size_str; + int mac_table_size; + idle_time_str = smap_get(&br->cfg->other_config, "mac-aging-time"); idle_time = (idle_time_str && atoi(idle_time_str) ? atoi(idle_time_str) : MAC_ENTRY_DEFAULT_IDLE_TIME); - ofproto_set_mac_idle_time(br->ofproto, idle_time); + + mac_table_size_str = smap_get(&br->cfg->other_config, "mac-table-size"); + mac_table_size = (mac_table_size_str && atoi(mac_table_size_str) + ? atoi(mac_table_size_str) + : MAC_DEFAULT_MAX); + + ofproto_set_mac_table_config(br->ofproto, idle_time, mac_table_size); } static void @@ -1606,15 +1617,10 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], found_addr = true; } } - if (found_addr) { - VLOG_DBG("bridge %s: using bridge Ethernet address "ETH_ADDR_FMT, - br->name, ETH_ADDR_ARGS(ea)); - } else { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10); + + if (!found_addr) { memcpy(ea, br->default_ea, ETH_ADDR_LEN); *hw_addr_iface = NULL; - VLOG_WARN_RL(&rl, "bridge %s: using default bridge Ethernet " - "address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(ea)); } hmapx_destroy(&mirror_output_ports); @@ -1705,7 +1711,7 @@ iface_refresh_status(struct iface *iface) smap_init(&smap); - if (!netdev_get_drv_info(iface->netdev, &smap)) { + if (!netdev_get_status(iface->netdev, &smap)) { ovsrec_interface_set_status(iface->cfg, &smap); } else { ovsrec_interface_set_status(iface->cfg, NULL); @@ -1834,7 +1840,7 @@ iface_refresh_stats(struct iface *iface) #define IFACE_STAT(MEMBER, NAME) values[i++] = stats.MEMBER; IFACE_STATS; #undef IFACE_STAT - assert(i == ARRAY_SIZE(keys)); + ovs_assert(i == ARRAY_SIZE(keys)); ovsrec_interface_set_statistics(iface->cfg, keys, values, ARRAY_SIZE(keys)); @@ -2109,7 +2115,7 @@ bridge_run_fast(void) void bridge_run(void) { - static const struct ovsrec_open_vswitch null_cfg; + static struct ovsrec_open_vswitch null_cfg; const struct ovsrec_open_vswitch *cfg; struct ovsdb_idl_txn *reconf_txn = NULL; struct sset types; @@ -2118,7 +2124,7 @@ bridge_run(void) bool vlan_splinters_changed; struct bridge *br; - ovsrec_open_vswitch_init((struct ovsrec_open_vswitch *) &null_cfg); + ovsrec_open_vswitch_init(&null_cfg); /* (Re)configure if necessary. */ if (!reconfiguring) { @@ -2396,7 +2402,7 @@ bridge_create(const struct ovsrec_bridge *br_cfg) { struct bridge *br; - assert(!bridge_lookup(br_cfg->name)); + ovs_assert(!bridge_lookup(br_cfg->name)); br = xzalloc(sizeof *br); br->name = xstrdup(br_cfg->name); @@ -2545,7 +2551,7 @@ bridge_queue_if_cfg(struct bridge *br, if_cfg->cfg = cfg; if_cfg->parent = parent; - if_cfg->ofport = cfg->n_ofport_request ? *cfg->ofport_request : OFPP_NONE; + if_cfg->ofport = iface_pick_ofport(cfg); hmap_insert(&br->if_cfg_todo, &if_cfg->hmap_node, hash_string(if_cfg->cfg->name, 0)); } @@ -2562,7 +2568,7 @@ bridge_add_del_ports(struct bridge *br, struct shash new_ports; size_t i; - assert(hmap_is_empty(&br->if_cfg_todo)); + ovs_assert(hmap_is_empty(&br->if_cfg_todo)); /* Collect new ports. */ shash_init(&new_ports); @@ -2707,7 +2713,7 @@ bridge_configure_local_iface_netdev(struct bridge *br, } if (!netdev_set_in4(netdev, ip, mask)) { VLOG_INFO("bridge %s: configured IP address "IP_FMT", netmask "IP_FMT, - br->name, IP_ARGS(&ip.s_addr), IP_ARGS(&mask.s_addr)); + br->name, IP_ARGS(ip.s_addr), IP_ARGS(mask.s_addr)); } /* Configure the default gateway. */ @@ -2716,19 +2722,30 @@ bridge_configure_local_iface_netdev(struct bridge *br, && gateway.s_addr) { if (!netdev_add_router(netdev, gateway)) { VLOG_INFO("bridge %s: configured gateway "IP_FMT, - br->name, IP_ARGS(&gateway.s_addr)); + br->name, IP_ARGS(gateway.s_addr)); } } } /* Returns true if 'a' and 'b' are the same except that any number of slashes * in either string are treated as equal to any number of slashes in the other, - * e.g. "x///y" is equal to "x/y". */ + * e.g. "x///y" is equal to "x/y". + * + * Also, if 'b_stoplen' bytes from 'b' are found to be equal to corresponding + * bytes from 'a', the function considers this success. Specify 'b_stoplen' as + * SIZE_MAX to compare all of 'a' to all of 'b' rather than just a prefix of + * 'b' against a prefix of 'a'. + */ static bool -equal_pathnames(const char *a, const char *b) +equal_pathnames(const char *a, const char *b, size_t b_stoplen) { - while (*a == *b) { - if (*a == '/') { + const char *b_start = b; + for (;;) { + if (b - b_start >= b_stoplen) { + return true; + } else if (*a != *b) { + return false; + } else if (*a == '/') { a += strspn(a, "/"); b += strspn(b, "/"); } else if (*a == '\0') { @@ -2738,7 +2755,6 @@ equal_pathnames(const char *a, const char *b) b++; } } - return false; } static void @@ -2785,21 +2801,40 @@ bridge_configure_remotes(struct bridge *br, static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); char *whitelist; - whitelist = xasprintf("unix:%s/%s.controller", + if (!strncmp(c->target, "unix:", 5)) { + /* Connect to a listening socket */ + whitelist = xasprintf("unix:%s/", ovs_rundir()); + if (!equal_pathnames(c->target, whitelist, + strlen(whitelist))) { + VLOG_ERR_RL(&rl, "bridge %s: Not connecting to socket " + "controller \"%s\" due to possibility for " + "remote exploit. Instead, specify socket " + "in whitelisted \"%s\" or connect to " + "\"unix:%s/%s.mgmt\" (which is always " + "available without special configuration).", + br->name, c->target, whitelist, ovs_rundir(), br->name); - if (!equal_pathnames(c->target, whitelist)) { - /* Prevent remote ovsdb-server users from accessing arbitrary - * Unix domain sockets and overwriting arbitrary local - * files. */ - VLOG_ERR_RL(&rl, "bridge %s: Not adding Unix domain socket " - "controller \"%s\" due to possibility for remote " - "exploit. Instead, specify whitelisted \"%s\" or " - "connect to \"unix:%s/%s.mgmt\" (which is always " - "available without special configuration).", - br->name, c->target, whitelist, - ovs_rundir(), br->name); - free(whitelist); - continue; + free(whitelist); + continue; + } + } else { + whitelist = xasprintf("punix:%s/%s.controller", + ovs_rundir(), br->name); + if (!equal_pathnames(c->target, whitelist, SIZE_MAX)) { + /* Prevent remote ovsdb-server users from accessing + * arbitrary Unix domain sockets and overwriting arbitrary + * local files. */ + VLOG_ERR_RL(&rl, "bridge %s: Not adding Unix domain socket " + "controller \"%s\" due to possibility of " + "overwriting local files. Instead, specify " + "whitelisted \"%s\" or connect to " + "\"unix:%s/%s.mgmt\" (which is always " + "available without special configuration).", + br->name, c->target, whitelist, + ovs_rundir(), br->name); + free(whitelist); + continue; + } } free(whitelist); @@ -2896,6 +2931,13 @@ bridge_configure_tables(struct bridge *br) br->cfg->key_flow_tables[j]); } } + +static void +bridge_configure_dp_desc(struct bridge *br) +{ + ofproto_set_dp_desc(br->ofproto, + smap_get(&br->cfg->other_config, "dp-desc")); +} /* Port functions. */ @@ -3308,7 +3350,6 @@ static void iface_clear_db_record(const struct ovsrec_interface *if_cfg) { if (!ovsdb_idl_row_is_synthetic(&if_cfg->header_)) { - iface_set_ofport(if_cfg, -1); ovsrec_interface_set_status(if_cfg, NULL); ovsrec_interface_set_admin_state(if_cfg, NULL); ovsrec_interface_set_duplex(if_cfg, NULL); @@ -3478,6 +3519,13 @@ iface_is_synthetic(const struct iface *iface) return ovsdb_idl_row_is_synthetic(&iface->cfg->header_); } +static int64_t +iface_pick_ofport(const struct ovsrec_interface *cfg) +{ + int64_t ofport = cfg->n_ofport ? *cfg->ofport : OFPP_NONE; + return cfg->n_ofport_request ? *cfg->ofport_request : ofport; +} + /* Port mirroring. */