X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=d1e24d0eeaaeba8c376cf63be5bb99dd269e40c5;hb=7beaa082d7f422dda337780d6dd457b9a5ffe7d5;hp=53454db449ceed9cba52273872dcf4f5cbd358b1;hpb=79f1cbe9f86ddfb1b5d92b80d85e09cd44768d6c;p=openvswitch diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 53454db4..d1e24d0e 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -36,6 +36,7 @@ #include "meta-flow.h" #include "netdev.h" #include "ofp-print.h" +#include "ofp-util.h" #include "ofpbuf.h" #include "ofproto/ofproto.h" #include "poll-loop.h" @@ -66,6 +67,7 @@ struct if_cfg { struct hmap_node hmap_node; /* Node in bridge's if_cfg_todo. */ const struct ovsrec_interface *cfg; /* Interface record. */ const struct ovsrec_port *parent; /* Parent port record. */ + int64_t ofport; /* Requested OpenFlow port number. */ }; /* OpenFlow port slated for removal from ofproto. */ @@ -148,16 +150,10 @@ static struct ovsdb_idl *idl; /* Most recently processed IDL sequence number. */ static unsigned int idl_seqno; -/* Each time this timer expires, the bridge fetches systems and interface +/* Each time this timer expires, the bridge fetches interface and mirror * statistics and pushes them into the database. */ -#define STATS_INTERVAL (5 * 1000) /* In milliseconds. */ -static long long int stats_timer = LLONG_MIN; - -/* Stores the time after which rate limited statistics may be written to the - * database. Only updated when changes to the database require rate limiting. - */ -#define DB_LIMIT_INTERVAL (1 * 1000) /* In milliseconds. */ -static long long int db_limiter = LLONG_MIN; +#define IFACE_STATS_INTERVAL (5 * 1000) /* In milliseconds. */ +static long long int iface_stats_timer = LLONG_MIN; /* In some datapaths, creating and destroying OpenFlow ports can be extremely * expensive. This can cause bridge_reconfigure() to take a long time during @@ -220,6 +216,9 @@ static void port_configure_bond(struct port *, struct bond_settings *, uint32_t *bond_stable_ids); static bool port_is_synthetic(const struct port *); +static void reconfigure_system_stats(const struct ovsrec_open_vswitch *); +static void run_system_stats(void); + static void bridge_configure_mirrors(struct bridge *); static struct mirror *mirror_create(struct bridge *, const struct ovsrec_mirror *); @@ -229,6 +228,8 @@ static void mirror_refresh_stats(struct mirror *); static void iface_configure_lacp(struct iface *, struct lacp_slave_settings *); static bool iface_create(struct bridge *, struct if_cfg *, int ofp_port); +static bool iface_is_internal(const struct ovsrec_interface *iface, + const struct ovsrec_bridge *br); static const char *iface_get_type(const struct ovsrec_interface *, const struct ovsrec_bridge *); static void iface_destroy(struct iface *); @@ -246,10 +247,6 @@ 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 void smap_from_ovs_idl_map(char **keys, char **values, size_t n, - struct smap *); -static void smap_to_ovs_idl_map(struct smap *, - char ***keys, char ***values, size_t *n); /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * @@ -268,6 +265,50 @@ 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 +bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg) +{ + struct shash iface_hints; + static bool initialized = false; + int i; + + if (initialized) { + return; + } + + shash_init(&iface_hints); + + if (cfg) { + for (i = 0; i < cfg->n_bridges; i++) { + const struct ovsrec_bridge *br_cfg = cfg->bridges[i]; + int 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 *if_cfg = port_cfg->interfaces[k]; + struct iface_hint *iface_hint; + + 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; + + shash_add(&iface_hints, if_cfg->name, iface_hint); + } + } + } + } + + ofproto_init(&iface_hints); + + shash_destroy_free_data(&iface_hints); + initialized = true; +} /* Public functions. */ @@ -281,6 +322,7 @@ bridge_init(const char *remote) idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true); idl_seqno = ovsdb_idl_get_seqno(idl); ovsdb_idl_set_lock(idl, "ovs_vswitchd"); + ovsdb_idl_verify_write_only(idl); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_cur_cfg); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_statistics); @@ -312,6 +354,7 @@ bridge_init(const char *remote) ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault_status); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_mpids); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_health); + ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_opstate); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_lacp_current); ovsdb_idl_omit(idl, &ovsrec_interface_col_external_ids); @@ -460,6 +503,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) iface_clear_db_record(if_cfg->cfg); } } + + reconfigure_system_stats(ovs_cfg); } static bool @@ -478,6 +523,11 @@ bridge_reconfigure_ofp(void) struct ofpp_garbage *garbage, *next; LIST_FOR_EACH_SAFE (garbage, next, list_node, &br->ofpp_garbage) { + /* It's a bit dangerous to call bridge_run_fast() here as ofproto's + * internal datastructures may not be consistent. Eventually, when + * port additions and deletions are cheaper, these calls should be + * removed. */ + bridge_run_fast(); ofproto_port_del(br->ofproto, garbage->ofp_port); list_remove(&garbage->list_node); free(garbage); @@ -486,6 +536,7 @@ bridge_reconfigure_ofp(void) if (time_msec() >= deadline) { return false; } + bridge_run_fast(); } } @@ -554,6 +605,8 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg) * forked us to exit successfully. */ daemonize_complete(); reconfiguring = false; + + VLOG_INFO("%s (Open vSwitch) %s", program_name, VERSION); } return done; @@ -688,8 +741,8 @@ port_configure(struct port *port) s.vlan_mode = PORT_VLAN_TRUNK; } } - s.use_priority_tags = !strcmp("true", ovsrec_port_get_other_config_value( - cfg, "priority-tags", "")); + s.use_priority_tags = smap_get_bool(&cfg->other_config, "priority-tags", + false); /* Get LACP settings. */ s.lacp = port_configure_lacp(port, &lacp_settings); @@ -752,13 +805,28 @@ bridge_configure_datapath_id(struct bridge *br) memcpy(br->ea, ea, ETH_ADDR_LEN); dpid = bridge_pick_datapath_id(br, ea, hw_addr_iface); - ofproto_set_datapath_id(br->ofproto, dpid); + if (dpid != ofproto_get_datapath_id(br->ofproto)) { + VLOG_INFO("bridge %s: using datapath ID %016"PRIx64, br->name, dpid); + ofproto_set_datapath_id(br->ofproto, dpid); + } dpid_string = xasprintf("%016"PRIx64, dpid); ovsrec_bridge_set_datapath_id(br->cfg, dpid_string); free(dpid_string); } +/* Returns a bitmap of "enum ofputil_protocol"s that are allowed for use with + * 'br'. */ +static uint32_t +bridge_get_allowed_versions(struct bridge *br) +{ + if (!br->cfg->n_protocols) + return 0; + + return ofputil_versions_from_strings(br->cfg->protocols, + br->cfg->n_protocols); +} + /* Set NetFlow configuration on 'br'. */ static void bridge_configure_netflow(struct bridge *br) @@ -879,9 +947,7 @@ port_configure_stp(const struct ofproto *ofproto, struct port *port, const char *config_str; struct iface *iface; - config_str = ovsrec_port_get_other_config_value(port->cfg, "stp-enable", - NULL); - if (config_str && !strcmp(config_str, "false")) { + if (!smap_get_bool(&port->cfg->other_config, "stp-enable", true)) { port_s->enable = false; return; } else { @@ -913,8 +979,7 @@ port_configure_stp(const struct ofproto *ofproto, struct port *port, return; } - config_str = ovsrec_port_get_other_config_value(port->cfg, "stp-port-num", - NULL); + config_str = smap_get(&port->cfg->other_config, "stp-port-num"); if (config_str) { unsigned long int port_num = strtoul(config_str, NULL, 0); int port_idx = port_num - 1; @@ -934,7 +999,7 @@ port_configure_stp(const struct ofproto *ofproto, struct port *port, bitmap_set1(port_num_bitmap, port_idx); port_s->port_num = port_idx; } else { - if (*port_num_counter > STP_MAX_PORTS) { + if (*port_num_counter >= STP_MAX_PORTS) { VLOG_ERR("port %s: too many STP ports, disabling", port->name); port_s->enable = false; return; @@ -943,27 +1008,19 @@ port_configure_stp(const struct ofproto *ofproto, struct port *port, port_s->port_num = (*port_num_counter)++; } - config_str = ovsrec_port_get_other_config_value(port->cfg, "stp-path-cost", - NULL); + config_str = smap_get(&port->cfg->other_config, "stp-path-cost"); if (config_str) { port_s->path_cost = strtoul(config_str, NULL, 10); } else { enum netdev_features current; + unsigned int mbps; - if (netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL)) { - /* Couldn't get speed, so assume 100Mb/s. */ - port_s->path_cost = 19; - } else { - unsigned int mbps; - - mbps = netdev_features_to_bps(current) / 1000000; - port_s->path_cost = stp_convert_speed_to_cost(mbps); - } + netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL); + mbps = netdev_features_to_bps(current, 100 * 1000 * 1000) / 1000000; + port_s->path_cost = stp_convert_speed_to_cost(mbps); } - config_str = ovsrec_port_get_other_config_value(port->cfg, - "stp-port-priority", - NULL); + config_str = smap_get(&port->cfg->other_config, "stp-port-priority"); if (config_str) { port_s->priority = strtoul(config_str, NULL, 0); } else { @@ -984,9 +1041,7 @@ bridge_configure_stp(struct bridge *br) int port_num_counter; unsigned long *port_num_bitmap; - config_str = ovsrec_bridge_get_other_config_value(br->cfg, - "stp-system-id", - NULL); + config_str = smap_get(&br->cfg->other_config, "stp-system-id"); if (config_str) { uint8_t ea[ETH_ADDR_LEN]; @@ -1001,36 +1056,28 @@ bridge_configure_stp(struct bridge *br) br_s.system_id = eth_addr_to_uint64(br->ea); } - config_str = ovsrec_bridge_get_other_config_value(br->cfg, - "stp-priority", - NULL); + config_str = smap_get(&br->cfg->other_config, "stp-priority"); if (config_str) { br_s.priority = strtoul(config_str, NULL, 0); } else { br_s.priority = STP_DEFAULT_BRIDGE_PRIORITY; } - config_str = ovsrec_bridge_get_other_config_value(br->cfg, - "stp-hello-time", - NULL); + config_str = smap_get(&br->cfg->other_config, "stp-hello-time"); if (config_str) { br_s.hello_time = strtoul(config_str, NULL, 10) * 1000; } else { br_s.hello_time = STP_DEFAULT_HELLO_TIME; } - config_str = ovsrec_bridge_get_other_config_value(br->cfg, - "stp-max-age", - NULL); + config_str = smap_get(&br->cfg->other_config, "stp-max-age"); if (config_str) { br_s.max_age = strtoul(config_str, NULL, 10) * 1000; } else { br_s.max_age = STP_DEFAULT_MAX_AGE; } - config_str = ovsrec_bridge_get_other_config_value(br->cfg, - "stp-forward-delay", - NULL); + config_str = smap_get(&br->cfg->other_config, "stp-forward-delay"); if (config_str) { br_s.fwd_delay = strtoul(config_str, NULL, 10) * 1000; } else { @@ -1151,16 +1198,9 @@ static int iface_set_netdev_config(const struct ovsrec_interface *iface_cfg, struct netdev *netdev) { - struct smap args; int error; - smap_init(&args); - smap_from_ovs_idl_map(iface_cfg->key_options, - iface_cfg->value_options, - iface_cfg->n_options, &args); - error = netdev_set_config(netdev, &args); - smap_destroy(&args); - + error = netdev_set_config(netdev, &iface_cfg->options); if (error) { VLOG_WARN("could not configure network device %s (%s)", iface_cfg->name, strerror(error)); @@ -1276,7 +1316,7 @@ bridge_refresh_ofp_port(struct bridge *br) } } -/* Opens a network device for 'iface_cfg' and configures it. If '*ofp_portp' +/* Opens a network device for 'if_cfg' and configures it. If '*ofp_portp' * is negative, adds the network device to br->ofproto and stores the OpenFlow * port number in '*ofp_portp'; otherwise leaves br->ofproto and '*ofp_portp' * untouched. @@ -1285,10 +1325,11 @@ bridge_refresh_ofp_port(struct bridge *br) * failure, returns a positive errno value and stores NULL in '*netdevp'. */ static int iface_do_create(const struct bridge *br, - const struct ovsrec_interface *iface_cfg, - const struct ovsrec_port *port_cfg, + const struct if_cfg *if_cfg, int *ofp_portp, struct netdev **netdevp) { + const struct ovsrec_interface *iface_cfg = if_cfg->cfg; + const struct ovsrec_port *port_cfg = if_cfg->parent; struct netdev *netdev; int error; @@ -1306,7 +1347,7 @@ iface_do_create(const struct bridge *br, } if (*ofp_portp < 0) { - uint16_t ofp_port; + uint16_t ofp_port = if_cfg->ofport; error = ofproto_port_add(br->ofproto, netdev, &ofp_port); if (error) { @@ -1321,7 +1362,8 @@ iface_do_create(const struct bridge *br, br->name, iface_cfg->name, *ofp_portp); } - if (port_cfg->vlan_mode && !strcmp(port_cfg->vlan_mode, "splinter")) { + if ((port_cfg->vlan_mode && !strcmp(port_cfg->vlan_mode, "splinter")) + || iface_is_internal(iface_cfg, br->cfg)) { netdev_turn_flags_on(netdev, NETDEV_UP, true); } @@ -1350,18 +1392,21 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) struct iface *iface; struct port *port; int error; + bool ok = true; - /* Get rid of 'if_cfg' itself. We already copied out the interesting - * bits. */ - hmap_remove(&br->if_cfg_todo, &if_cfg->hmap_node); - free(if_cfg); - - /* Do the bits that can fail up front. */ + /* Do the bits that can fail up front. + * + * It's a bit dangerous to call bridge_run_fast() here as ofproto's + * 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)); - error = iface_do_create(br, iface_cfg, port_cfg, &ofp_port, &netdev); + error = iface_do_create(br, if_cfg, &ofp_port, &netdev); + bridge_run_fast(); if (error) { iface_clear_db_record(iface_cfg); - return false; + ok = false; + goto done; } /* Get or create the port structure. */ @@ -1399,7 +1444,9 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) error = netdev_open(port->name, "internal", &netdev); if (!error) { - ofproto_port_add(br->ofproto, netdev, NULL); + uint16_t ofp_port = if_cfg->ofport; + + ofproto_port_add(br->ofproto, netdev, &ofp_port); netdev_close(netdev); } else { VLOG_WARN("could not open network device %s (%s)", @@ -1411,7 +1458,11 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) } } - return true; +done: + hmap_remove(&br->if_cfg_todo, &if_cfg->hmap_node); + free(if_cfg); + + return ok; } /* Set Flow eviction threshold */ @@ -1421,14 +1472,12 @@ bridge_configure_flow_eviction_threshold(struct bridge *br) const char *threshold_str; unsigned threshold; - threshold_str = - ovsrec_bridge_get_other_config_value(br->cfg, - "flow-eviction-threshold", - NULL); + threshold_str = smap_get(&br->cfg->other_config, + "flow-eviction-threshold"); if (threshold_str) { threshold = strtoul(threshold_str, NULL, 10); } else { - threshold = OFPROTO_FLOW_EVICTON_THRESHOLD_DEFAULT; + threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT; } ofproto_set_flow_eviction_threshold(br->ofproto, threshold); } @@ -1437,16 +1486,10 @@ bridge_configure_flow_eviction_threshold(struct bridge *br) static void bridge_configure_forward_bpdu(struct bridge *br) { - const char *forward_bpdu_str; - bool forward_bpdu = false; - - forward_bpdu_str = ovsrec_bridge_get_other_config_value(br->cfg, - "forward-bpdu", - NULL); - if (forward_bpdu_str && !strcmp(forward_bpdu_str, "true")) { - forward_bpdu = true; - } - ofproto_set_forward_bpdu(br->ofproto, forward_bpdu); + ofproto_set_forward_bpdu(br->ofproto, + smap_get_bool(&br->cfg->other_config, + "forward-bpdu", + false)); } /* Set MAC aging time for 'br'. */ @@ -1456,9 +1499,7 @@ bridge_configure_mac_idle_time(struct bridge *br) const char *idle_time_str; int idle_time; - idle_time_str = ovsrec_bridge_get_other_config_value(br->cfg, - "mac-aging-time", - NULL); + 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); @@ -1479,7 +1520,7 @@ bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN], *hw_addr_iface = NULL; /* Did the user request a particular MAC? */ - hwaddr = ovsrec_bridge_get_other_config_value(br->cfg, "hwaddr", NULL); + hwaddr = smap_get(&br->cfg->other_config, "hwaddr"); if (hwaddr && eth_addr_from_string(hwaddr, ea)) { if (eth_addr_is_multicast(ea)) { VLOG_ERR("bridge %s: cannot set MAC address to multicast " @@ -1604,8 +1645,7 @@ bridge_pick_datapath_id(struct bridge *br, const char *datapath_id; uint64_t dpid; - datapath_id = ovsrec_bridge_get_other_config_value(br->cfg, "datapath-id", - NULL); + datapath_id = smap_get(&br->cfg->other_config, "datapath-id"); if (datapath_id && dpid_from_string(datapath_id, &dpid)) { return dpid; } @@ -1654,7 +1694,6 @@ iface_refresh_status(struct iface *iface) struct smap smap; enum netdev_features current; - enum netdev_flags flags; int64_t bps; int mtu; int64_t mtu_64; @@ -1667,36 +1706,19 @@ iface_refresh_status(struct iface *iface) smap_init(&smap); if (!netdev_get_drv_info(iface->netdev, &smap)) { - size_t n; - char **keys, **values; - - smap_to_ovs_idl_map(&smap, &keys, &values, &n); - ovsrec_interface_set_status(iface->cfg, keys, values, n); - - free(keys); - free(values); + ovsrec_interface_set_status(iface->cfg, &smap); } else { - ovsrec_interface_set_status(iface->cfg, NULL, NULL, 0); + ovsrec_interface_set_status(iface->cfg, NULL); } smap_destroy(&smap); - error = netdev_get_flags(iface->netdev, &flags); - if (!error) { - ovsrec_interface_set_admin_state(iface->cfg, - flags & NETDEV_UP ? "up" : "down"); - } - else { - ovsrec_interface_set_admin_state(iface->cfg, NULL); - } - error = netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL); - if (!error) { + bps = !error ? netdev_features_to_bps(current, 0) : 0; + if (bps) { ovsrec_interface_set_duplex(iface->cfg, netdev_features_is_full_duplex(current) ? "full" : "half"); - /* warning: uint64_t -> int64_t conversion */ - bps = netdev_features_to_bps(current); ovsrec_interface_set_link_speed(iface->cfg, &bps, 1); } else { @@ -1714,20 +1736,17 @@ iface_refresh_status(struct iface *iface) } } -/* Writes 'iface''s CFM statistics to the database. */ +/* Writes 'iface''s CFM statistics to the database. 'iface' must not be + * synthetic. */ static void iface_refresh_cfm_stats(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - int fault, error; + int fault, opup, error; const uint64_t *rmps; size_t n_rmps; int health; - if (iface_is_synthetic(iface)) { - return; - } - fault = ofproto_port_get_cfm_fault(iface->port->bridge->ofproto, iface->ofp_port); if (fault >= 0) { @@ -1750,6 +1769,14 @@ iface_refresh_cfm_stats(struct iface *iface) ovsrec_interface_set_cfm_fault_status(cfg, NULL, 0); } + opup = ofproto_port_get_cfm_opup(iface->port->bridge->ofproto, + iface->ofp_port); + if (opup >= 0) { + ovsrec_interface_set_cfm_remote_opstate(cfg, opup ? "up" : "down"); + } else { + ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); + } + error = ofproto_port_get_cfm_remote_mpids(iface->port->bridge->ofproto, iface->ofp_port, &rmps, &n_rmps); if (error >= 0) { @@ -1817,32 +1844,27 @@ iface_refresh_stats(struct iface *iface) static void br_refresh_stp_status(struct bridge *br) { + struct smap smap = SMAP_INITIALIZER(&smap); struct ofproto *ofproto = br->ofproto; struct ofproto_stp_status status; - char *keys[3], *values[3]; - size_t i; if (ofproto_get_stp_status(ofproto, &status)) { return; } if (!status.enabled) { - ovsrec_bridge_set_status(br->cfg, NULL, NULL, 0); + ovsrec_bridge_set_status(br->cfg, NULL); return; } - keys[0] = "stp_bridge_id", - values[0] = xasprintf(STP_ID_FMT, STP_ID_ARGS(status.bridge_id)); - keys[1] = "stp_designated_root", - values[1] = xasprintf(STP_ID_FMT, STP_ID_ARGS(status.designated_root)); - keys[2] = "stp_root_path_cost", - values[2] = xasprintf("%d", status.root_path_cost); - - ovsrec_bridge_set_status(br->cfg, keys, values, ARRAY_SIZE(values)); + smap_add_format(&smap, "stp_bridge_id", STP_ID_FMT, + STP_ID_ARGS(status.bridge_id)); + smap_add_format(&smap, "stp_designated_root", STP_ID_FMT, + STP_ID_ARGS(status.designated_root)); + smap_add_format(&smap, "stp_root_path_cost", "%d", status.root_path_cost); - for (i = 0; i < ARRAY_SIZE(values); i++) { - free(values[i]); - } + ovsrec_bridge_set_status(br->cfg, &smap); + smap_destroy(&smap); } static void @@ -1851,10 +1873,9 @@ port_refresh_stp_status(struct port *port) struct ofproto *ofproto = port->bridge->ofproto; struct iface *iface; struct ofproto_port_stp_status status; - char *keys[4]; - char *str_values[4]; + char *keys[3]; int64_t int_values[3]; - size_t i; + struct smap smap; if (port_is_synthetic(port)) { return; @@ -1862,7 +1883,7 @@ port_refresh_stp_status(struct port *port) /* STP doesn't currently support bonds. */ if (!list_is_singleton(&port->ifaces)) { - ovsrec_port_set_status(port->cfg, NULL, NULL, 0); + ovsrec_port_set_status(port->cfg, NULL); return; } @@ -1873,27 +1894,19 @@ port_refresh_stp_status(struct port *port) } if (!status.enabled) { - ovsrec_port_set_status(port->cfg, NULL, NULL, 0); + ovsrec_port_set_status(port->cfg, NULL); ovsrec_port_set_statistics(port->cfg, NULL, NULL, 0); return; } /* Set Status column. */ - keys[0] = "stp_port_id"; - str_values[0] = xasprintf(STP_PORT_ID_FMT, status.port_id); - keys[1] = "stp_state"; - str_values[1] = xstrdup(stp_state_name(status.state)); - keys[2] = "stp_sec_in_state"; - str_values[2] = xasprintf("%u", status.sec_in_state); - keys[3] = "stp_role"; - str_values[3] = xstrdup(stp_role_name(status.role)); - - ovsrec_port_set_status(port->cfg, keys, str_values, - ARRAY_SIZE(str_values)); - - for (i = 0; i < ARRAY_SIZE(str_values); i++) { - free(str_values[i]); - } + smap_init(&smap); + smap_add_format(&smap, "stp_port_id", STP_PORT_ID_FMT, status.port_id); + smap_add(&smap, "stp_state", stp_state_name(status.state)); + smap_add_format(&smap, "stp_sec_in_state", "%u", status.sec_in_state); + smap_add(&smap, "stp_role", stp_role_name(status.role)); + ovsrec_port_set_status(port->cfg, &smap); + smap_destroy(&smap); /* Set Statistics column. */ keys[0] = "stp_tx_count"; @@ -1910,34 +1923,40 @@ port_refresh_stp_status(struct port *port) static bool enable_system_stats(const struct ovsrec_open_vswitch *cfg) { - const char *enable; + return smap_get_bool(&cfg->other_config, "enable-statistics", false); +} - /* Use other-config:enable-system-stats by preference. */ - enable = ovsrec_open_vswitch_get_other_config_value(cfg, - "enable-statistics", - NULL); - if (enable) { - return !strcmp(enable, "true"); - } +static void +reconfigure_system_stats(const struct ovsrec_open_vswitch *cfg) +{ + bool enable = enable_system_stats(cfg); - /* Disable by default. */ - return false; + system_stats_enable(enable); + if (!enable) { + ovsrec_open_vswitch_set_statistics(cfg, NULL); + } } static void -refresh_system_stats(const struct ovsrec_open_vswitch *cfg) +run_system_stats(void) { - struct ovsdb_datum datum; - struct shash stats; + const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(idl); + struct smap *stats; - shash_init(&stats); - if (enable_system_stats(cfg)) { - get_system_stats(&stats); - } + stats = system_stats_run(); + if (stats && cfg) { + struct ovsdb_idl_txn *txn; + struct ovsdb_datum datum; - ovsdb_datum_from_shash(&datum, &stats); - ovsdb_idl_txn_write(&cfg->header_, &ovsrec_open_vswitch_col_statistics, - &datum); + txn = ovsdb_idl_txn_create(idl); + ovsdb_datum_from_smap(&datum, stats); + ovsdb_idl_txn_write(&cfg->header_, &ovsrec_open_vswitch_col_statistics, + &datum); + ovsdb_idl_txn_commit(txn); + ovsdb_idl_txn_destroy(txn); + + free(stats); + } } static inline const char * @@ -1975,15 +1994,23 @@ refresh_controller_status(void) shash_find_data(&info, cfg->target); if (cinfo) { + struct smap smap = SMAP_INITIALIZER(&smap); + const char **values = cinfo->pairs.values; + const char **keys = cinfo->pairs.keys; + size_t i; + + for (i = 0; i < cinfo->pairs.n; i++) { + smap_add(&smap, keys[i], values[i]); + } + ovsrec_controller_set_is_connected(cfg, cinfo->is_connected); ovsrec_controller_set_role(cfg, nx_role_to_str(cinfo->role)); - ovsrec_controller_set_status(cfg, (char **) cinfo->pairs.keys, - (char **) cinfo->pairs.values, - cinfo->pairs.n); + ovsrec_controller_set_status(cfg, &smap); + smap_destroy(&smap); } else { ovsrec_controller_set_is_connected(cfg, false); ovsrec_controller_set_role(cfg, NULL); - ovsrec_controller_set_status(cfg, NULL, NULL, 0); + ovsrec_controller_set_status(cfg, NULL); } } @@ -1991,7 +2018,7 @@ refresh_controller_status(void) } static void -refresh_cfm_stats(void) +refresh_instant_stats(void) { static struct ovsdb_idl_txn *txn = NULL; @@ -2002,8 +2029,47 @@ refresh_cfm_stats(void) HMAP_FOR_EACH (br, node, &all_bridges) { struct iface *iface; + struct port *port; + + br_refresh_stp_status(br); + + HMAP_FOR_EACH (port, hmap_node, &br->ports) { + port_refresh_stp_status(port); + } HMAP_FOR_EACH (iface, name_node, &br->iface_by_name) { + enum netdev_flags flags; + const char *link_state; + int64_t link_resets; + int current, error; + + if (iface_is_synthetic(iface)) { + continue; + } + + current = ofproto_port_is_lacp_current(br->ofproto, + iface->ofp_port); + if (current >= 0) { + bool bl = current; + ovsrec_interface_set_lacp_current(iface->cfg, &bl, 1); + } else { + ovsrec_interface_set_lacp_current(iface->cfg, NULL, 0); + } + + error = netdev_get_flags(iface->netdev, &flags); + if (!error) { + const char *state = flags & NETDEV_UP ? "up" : "down"; + ovsrec_interface_set_admin_state(iface->cfg, state); + } else { + ovsrec_interface_set_admin_state(iface->cfg, NULL); + } + + link_state = netdev_get_carrier(iface->netdev) ? "up" : "down"; + ovsrec_interface_set_link_state(iface->cfg, link_state); + + link_resets = netdev_get_carrier_resets(iface->netdev); + ovsrec_interface_set_link_resets(iface->cfg, &link_resets, 1); + iface_refresh_cfm_stats(iface); } } @@ -2024,8 +2090,17 @@ refresh_cfm_stats(void) void bridge_run_fast(void) { + struct sset types; + const char *type; struct bridge *br; + sset_init(&types); + ofproto_enumerate_types(&types); + SSET_FOR_EACH (type, &types) { + ofproto_type_run_fast(type); + } + sset_destroy(&types); + HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_run_fast(br->ofproto); } @@ -2037,10 +2112,14 @@ bridge_run(void) static const struct ovsrec_open_vswitch null_cfg; const struct ovsrec_open_vswitch *cfg; struct ovsdb_idl_txn *reconf_txn = NULL; + struct sset types; + const char *type; bool vlan_splinters_changed; struct bridge *br; + ovsrec_open_vswitch_init((struct ovsrec_open_vswitch *) &null_cfg); + /* (Re)configure if necessary. */ if (!reconfiguring) { ovsdb_idl_run(idl); @@ -2062,6 +2141,20 @@ bridge_run(void) } cfg = ovsrec_open_vswitch_first(idl); + /* Initialize the ofproto library. This only needs to run once, but + * it must be done after the configuration is set. If the + * initialization has already occurred, bridge_init_ofproto() + * returns immediately. */ + bridge_init_ofproto(cfg); + + /* Let each datapath type do the work that it needs to do. */ + sset_init(&types); + ofproto_enumerate_types(&types); + SSET_FOR_EACH (type, &types) { + ofproto_type_run(type); + } + sset_destroy(&types); + /* Let each bridge do the work that it needs to do. */ HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_run(br->ofproto); @@ -2125,8 +2218,8 @@ bridge_run(void) reconf_txn = NULL; } - /* Refresh system and interface stats if necessary. */ - if (time_msec() >= stats_timer) { + /* Refresh interface and mirror stats if necessary. */ + if (time_msec() >= iface_stats_timer) { if (cfg) { struct ovsdb_idl_txn *txn; @@ -2149,85 +2242,47 @@ bridge_run(void) } } - refresh_system_stats(cfg); refresh_controller_status(); ovsdb_idl_txn_commit(txn); ovsdb_idl_txn_destroy(txn); /* XXX */ } - stats_timer = time_msec() + STATS_INTERVAL; - } - - if (time_msec() >= db_limiter) { - struct ovsdb_idl_txn *txn; - - txn = ovsdb_idl_txn_create(idl); - HMAP_FOR_EACH (br, node, &all_bridges) { - struct iface *iface; - struct port *port; - - br_refresh_stp_status(br); - - HMAP_FOR_EACH (port, hmap_node, &br->ports) { - port_refresh_stp_status(port); - } - - HMAP_FOR_EACH (iface, name_node, &br->iface_by_name) { - const char *link_state; - int64_t link_resets; - int current; - - if (iface_is_synthetic(iface)) { - continue; - } - - current = ofproto_port_is_lacp_current(br->ofproto, - iface->ofp_port); - if (current >= 0) { - bool bl = current; - ovsrec_interface_set_lacp_current(iface->cfg, &bl, 1); - } else { - ovsrec_interface_set_lacp_current(iface->cfg, NULL, 0); - } - - link_state = netdev_get_carrier(iface->netdev) ? "up" : "down"; - ovsrec_interface_set_link_state(iface->cfg, link_state); - - link_resets = netdev_get_carrier_resets(iface->netdev); - ovsrec_interface_set_link_resets(iface->cfg, &link_resets, 1); - } - } - - if (ovsdb_idl_txn_commit(txn) != TXN_UNCHANGED) { - db_limiter = time_msec() + DB_LIMIT_INTERVAL; - } - ovsdb_idl_txn_destroy(txn); + iface_stats_timer = time_msec() + IFACE_STATS_INTERVAL; } - refresh_cfm_stats(); + run_system_stats(); + refresh_instant_stats(); } void bridge_wait(void) { + struct sset types; + const char *type; + ovsdb_idl_wait(idl); if (reconfiguring) { poll_immediate_wake(); } + sset_init(&types); + ofproto_enumerate_types(&types); + SSET_FOR_EACH (type, &types) { + ofproto_type_wait(type); + } + sset_destroy(&types); + if (!hmap_is_empty(&all_bridges)) { struct bridge *br; HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_wait(br->ofproto); } - poll_timer_wait_until(stats_timer); - - if (db_limiter > time_msec()) { - poll_timer_wait_until(db_limiter); - } + poll_timer_wait_until(iface_stats_timer); } + + system_stats_wait(); } /* Adds some memory usage statistics for bridges into 'usage', for use with @@ -2490,6 +2545,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; hmap_insert(&br->if_cfg_todo, &if_cfg->hmap_node, hash_string(if_cfg->cfg->name, 0)); } @@ -2522,6 +2578,9 @@ bridge_add_del_ports(struct bridge *br, VLOG_WARN("bridge %s: no port named %s, synthesizing one", br->name, br->name); + ovsrec_interface_init(&br->synth_local_iface); + ovsrec_port_init(&br->synth_local_port); + br->synth_local_port.interfaces = &br->synth_local_ifacep; br->synth_local_port.n_interfaces = 1; br->synth_local_port.name = br->name; @@ -2563,7 +2622,12 @@ bridge_add_del_ports(struct bridge *br, if (iface) { iface->cfg = cfg; iface->type = type; - } else if (strcmp(type, "null")) { + } else if (!strcmp(type, "null")) { + VLOG_WARN_ONCE("%s: The null interface type is deprecated and" + " may be removed in February 2013. Please email" + " dev@openvswitch.org with concerns.", + cfg->name); + } else { bridge_queue_if_cfg(br, cfg, port); } } @@ -2594,7 +2658,7 @@ static void bridge_ofproto_controller_from_ovsrec(const struct ovsrec_controller *c, struct ofproto_controller *oc) { - const char *config_str; + int dscp; oc->target = c->target; oc->max_backoff = c->max_backoff ? *c->max_backoff / 1000 : 8; @@ -2606,16 +2670,11 @@ bridge_ofproto_controller_from_ovsrec(const struct ovsrec_controller *c, ? *c->controller_burst_limit : 0); oc->enable_async_msgs = (!c->enable_async_messages || *c->enable_async_messages); - config_str = ovsrec_controller_get_other_config_value(c, "dscp", NULL); - - oc->dscp = DSCP_DEFAULT; - if (config_str) { - int dscp = atoi(config_str); - - if (dscp >= 0 && dscp <= 63) { - oc->dscp = dscp; - } + dscp = smap_get_int(&c->other_config, "dscp", DSCP_DEFAULT); + if (dscp < 0 || dscp > 63) { + dscp = DSCP_DEFAULT; } + oc->dscp = dscp; } /* Configures the IP stack for 'br''s local interface properly according to the @@ -2686,9 +2745,7 @@ static void bridge_configure_remotes(struct bridge *br, const struct sockaddr_in *managers, size_t n_managers) { - const char *disable_ib_str, *queue_id_str; - bool disable_in_band = false; - int queue_id; + bool disable_in_band; struct ovsrec_controller **controllers; size_t n_controllers; @@ -2700,19 +2757,13 @@ bridge_configure_remotes(struct bridge *br, size_t i; /* Check if we should disable in-band control on this bridge. */ - disable_ib_str = ovsrec_bridge_get_other_config_value(br->cfg, - "disable-in-band", - NULL); - if (disable_ib_str && !strcmp(disable_ib_str, "true")) { - disable_in_band = true; - } + disable_in_band = smap_get_bool(&br->cfg->other_config, "disable-in-band", + false); /* Set OpenFlow queue ID for in-band control. */ - queue_id_str = ovsrec_bridge_get_other_config_value(br->cfg, - "in-band-queue", - NULL); - queue_id = queue_id_str ? strtol(queue_id_str, NULL, 10) : -1; - ofproto_set_in_band_queue(br->ofproto, queue_id); + ofproto_set_in_band_queue(br->ofproto, + smap_get_int(&br->cfg->other_config, + "in-band-queue", -1)); if (disable_in_band) { ofproto_set_extra_in_band_remotes(br->ofproto, NULL, 0); @@ -2762,7 +2813,8 @@ bridge_configure_remotes(struct bridge *br, n_ocs++; } - ofproto_set_controllers(br->ofproto, ocs, n_ocs); + ofproto_set_controllers(br->ofproto, ocs, n_ocs, + bridge_get_allowed_versions(br)); free(ocs[0].target); /* From bridge_ofproto_controller_for_mgmt(). */ free(ocs); @@ -2959,8 +3011,7 @@ port_configure_lacp(struct port *port, struct lacp_settings *s) s->name = port->name; - system_id = ovsrec_port_get_other_config_value(port->cfg, "lacp-system-id", - NULL); + system_id = smap_get(&port->cfg->other_config, "lacp-system-id"); if (system_id) { if (sscanf(system_id, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(s->id)) != ETH_ADDR_SCAN_COUNT) { @@ -2978,16 +3029,14 @@ port_configure_lacp(struct port *port, struct lacp_settings *s) } /* Prefer bondable links if unspecified. */ - priority = atoi(ovsrec_port_get_other_config_value(port->cfg, - "lacp-system-priority", - "0")); + priority = smap_get_int(&port->cfg->other_config, "lacp-system-priority", + 0); s->priority = (priority > 0 && priority <= UINT16_MAX ? priority : UINT16_MAX - !list_is_short(&port->ifaces)); - lacp_time = ovsrec_port_get_other_config_value(port->cfg, "lacp-time", - "slow"); - s->fast = !strcasecmp(lacp_time, "fast"); + lacp_time = smap_get(&port->cfg->other_config, "lacp-time"); + s->fast = lacp_time && !strcasecmp(lacp_time, "fast"); return s; } @@ -2996,16 +3045,10 @@ iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s) { int priority, portid, key; - portid = atoi(ovsrec_interface_get_other_config_value(iface->cfg, - "lacp-port-id", - "0")); - priority = - atoi(ovsrec_interface_get_other_config_value(iface->cfg, - "lacp-port-priority", - "0")); - key = atoi(ovsrec_interface_get_other_config_value(iface->cfg, - "lacp-aggregation-key", - "0")); + portid = smap_get_int(&iface->cfg->other_config, "lacp-port-id", 0); + priority = smap_get_int(&iface->cfg->other_config, "lacp-port-priority", + 0); + key = smap_get_int(&iface->cfg->other_config, "lacp-aggregation-key", 0); if (portid <= 0 || portid > UINT16_MAX) { portid = iface->ofp_port; @@ -3058,17 +3101,14 @@ port_configure_bond(struct port *port, struct bond_settings *s, port->name); } - miimon_interval = - atoi(ovsrec_port_get_other_config_value(port->cfg, - "bond-miimon-interval", "0")); + miimon_interval = smap_get_int(&port->cfg->other_config, + "bond-miimon-interval", 0); if (miimon_interval <= 0) { miimon_interval = 200; } - detect_s = ovsrec_port_get_other_config_value(port->cfg, - "bond-detect-mode", - "carrier"); - if (!strcmp(detect_s, "carrier")) { + detect_s = smap_get(&port->cfg->other_config, "bond-detect-mode"); + if (!detect_s || !strcmp(detect_s, "carrier")) { miimon_interval = 0; } else if (strcmp(detect_s, "miimon")) { VLOG_WARN("port %s: unsupported bond-detect-mode %s, " @@ -3078,13 +3118,9 @@ port_configure_bond(struct port *port, struct bond_settings *s, s->up_delay = MAX(0, port->cfg->bond_updelay); s->down_delay = MAX(0, port->cfg->bond_downdelay); - s->basis = atoi(ovsrec_port_get_other_config_value(port->cfg, - "bond-hash-basis", - "0")); - s->rebalance_interval = atoi( - ovsrec_port_get_other_config_value(port->cfg, - "bond-rebalance-interval", - "10000")); + s->basis = smap_get_int(&port->cfg->other_config, "bond-hash-basis", 0); + s->rebalance_interval = smap_get_int(&port->cfg->other_config, + "bond-rebalance-interval", 10000); if (s->rebalance_interval && s->rebalance_interval < 1000) { s->rebalance_interval = 1000; } @@ -3095,10 +3131,8 @@ port_configure_bond(struct port *port, struct bond_settings *s, LIST_FOR_EACH (iface, port_elem, &port->ifaces) { long long stable_id; - stable_id = - atoll(ovsrec_interface_get_other_config_value(iface->cfg, - "bond-stable-id", - "0")); + stable_id = smap_get_int(&iface->cfg->other_config, "bond-stable-id", + 0); if (stable_id <= 0 || stable_id >= UINT32_MAX) { stable_id = iface->ofp_port; } @@ -3118,17 +3152,32 @@ port_is_synthetic(const struct port *port) /* Interface functions. */ +static bool +iface_is_internal(const struct ovsrec_interface *iface, + const struct ovsrec_bridge *br) +{ + /* The local port and "internal" ports are always "internal". */ + return !strcmp(iface->type, "internal") || !strcmp(iface->name, br->name); +} + /* Returns the correct network device type for interface 'iface' in bridge * 'br'. */ static const char * iface_get_type(const struct ovsrec_interface *iface, const struct ovsrec_bridge *br) { - /* The local port always has type "internal". Other ports take their type - * from the database and default to "system" if none is specified. */ - return (!strcmp(iface->name, br->name) ? "internal" - : iface->type[0] ? iface->type - : "system"); + const char *type; + + /* The local port always has type "internal". Other ports take + * their type from the database and default to "system" if none is + * specified. */ + if (iface_is_internal(iface, br)) { + type = "internal"; + } else { + type = iface->type[0] ? iface->type : "system"; + } + + return ofproto_port_open_type(br->datapath_type, type); } static void @@ -3260,7 +3309,7 @@ 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, NULL, 0); + ovsrec_interface_set_status(if_cfg, NULL); ovsrec_interface_set_admin_state(if_cfg, NULL); ovsrec_interface_set_duplex(if_cfg, NULL); ovsrec_interface_set_link_speed(if_cfg, NULL, 0); @@ -3274,50 +3323,6 @@ iface_clear_db_record(const struct ovsrec_interface *if_cfg) } } -/* Adds the 'n' key-value pairs in 'keys' in 'values' to 'shash'. */ -static void -smap_from_ovs_idl_map(char **keys, char **values, size_t n, struct smap *smap) -{ - size_t i; - - smap_init(smap); - for (i = 0; i < n; i++) { - smap_add(smap, keys[i], values[i]); - } -} - -/* Creates 'keys' and 'values' arrays from 'shash'. - * - * Sets 'keys' and 'values' to heap allocated arrays representing the key-value - * pairs in 'smap'. The caller takes ownership of 'keys' and 'values'. They - * are populated with with strings taken directly from 'shash' and thus have - * the same ownership of the key-value pairs in shash. - */ -static void -smap_to_ovs_idl_map(struct smap *smap, - char ***keys, char ***values, size_t *n) -{ - size_t i, count; - char **k, **v; - struct smap_node *sn; - - count = smap_count(smap); - - k = xmalloc(count * sizeof *k); - v = xmalloc(count * sizeof *v); - - i = 0; - SMAP_FOR_EACH(sn, smap) { - k[i] = sn->key; - v[i] = sn->value; - i++; - } - - *n = count; - *keys = k; - *values = v; -} - struct iface_delete_queues_cbdata { struct netdev *netdev; const struct ovsdb_datum *queues; @@ -3354,15 +3359,11 @@ iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos) netdev_set_qos(iface->netdev, NULL, NULL); } else { struct iface_delete_queues_cbdata cbdata; - struct smap details; bool queue_zero; size_t i; /* Configure top-level Qos for 'iface'. */ - smap_from_ovs_idl_map(qos->key_other_config, qos->value_other_config, - qos->n_other_config, &details); - netdev_set_qos(iface->netdev, qos->type, &details); - smap_destroy(&details); + netdev_set_qos(iface->netdev, qos->type, &qos->other_config); /* Deconfigure queues that were deleted. */ cbdata.netdev = iface->netdev; @@ -3389,13 +3390,11 @@ iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos) port_queue->dscp = queue->dscp[0]; } - smap_from_ovs_idl_map(queue->key_other_config, - queue->value_other_config, - queue->n_other_config, &details); - netdev_set_queue(iface->netdev, queue_id, &details); - smap_destroy(&details); + netdev_set_queue(iface->netdev, queue_id, &queue->other_config); } if (!queue_zero) { + struct smap details; + smap_init(&details); netdev_set_queue(iface->netdev, 0, &details); smap_destroy(&details); @@ -3421,30 +3420,39 @@ static void iface_configure_cfm(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; - const char *extended_str, *opstate_str; + const char *opstate_str; const char *cfm_ccm_vlan; struct cfm_settings s; + struct smap netdev_args; if (!cfg->n_cfm_mpid) { ofproto_port_clear_cfm(iface->port->bridge->ofproto, iface->ofp_port); return; } + s.check_tnl_key = false; + smap_init(&netdev_args); + if (!netdev_get_config(iface->netdev, &netdev_args)) { + const char *key = smap_get(&netdev_args, "key"); + const char *in_key = smap_get(&netdev_args, "in_key"); + + s.check_tnl_key = (key && !strcmp(key, "flow")) + || (in_key && !strcmp(in_key, "flow")); + } + smap_destroy(&netdev_args); + s.mpid = *cfg->cfm_mpid; - s.interval = atoi(ovsrec_interface_get_other_config_value(iface->cfg, - "cfm_interval", - "0")); - cfm_ccm_vlan = ovsrec_interface_get_other_config_value(iface->cfg, - "cfm_ccm_vlan", - "0"); - s.ccm_pcp = atoi(ovsrec_interface_get_other_config_value(iface->cfg, - "cfm_ccm_pcp", - "0")); + s.interval = smap_get_int(&iface->cfg->other_config, "cfm_interval", 0); + cfm_ccm_vlan = smap_get(&iface->cfg->other_config, "cfm_ccm_vlan"); + s.ccm_pcp = smap_get_int(&iface->cfg->other_config, "cfm_ccm_pcp", 0); + if (s.interval <= 0) { s.interval = 1000; } - if (!strcasecmp("random", cfm_ccm_vlan)) { + if (!cfm_ccm_vlan) { + s.ccm_vlan = 0; + } else if (!strcasecmp("random", cfm_ccm_vlan)) { s.ccm_vlan = CFM_RANDOM_VLAN; } else { s.ccm_vlan = atoi(cfm_ccm_vlan); @@ -3453,15 +3461,11 @@ iface_configure_cfm(struct iface *iface) } } - extended_str = ovsrec_interface_get_other_config_value(iface->cfg, - "cfm_extended", - "false"); - s.extended = !strcasecmp("true", extended_str); + s.extended = smap_get_bool(&iface->cfg->other_config, "cfm_extended", + false); - opstate_str = ovsrec_interface_get_other_config_value(iface->cfg, - "cfm_opstate", - "up"); - s.opup = !strcasecmp("up", opstate_str); + opstate_str = smap_get(&iface->cfg->other_config, "cfm_opstate"); + s.opup = !opstate_str || !strcasecmp("up", opstate_str); ofproto_port_set_cfm(iface->port->bridge->ofproto, iface->ofp_port, &s); } @@ -3699,12 +3703,10 @@ free_registered_recs(void) free(iface); } + smap_destroy(&port->other_config); free(port->interfaces); free(port->name); free(port->tag); - free(port->key_other_config); - free(port->value_other_config[0]); - free(port->value_other_config); free(port); } n_recs = 0; @@ -3715,12 +3717,8 @@ free_registered_recs(void) static bool vlan_splinters_is_enabled(const struct ovsrec_interface *iface_cfg) { - const char *value; - - value = ovsrec_interface_get_other_config_value(iface_cfg, - "enable-vlan-splinters", - ""); - return !strcmp(value, "true"); + 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 @@ -3864,8 +3862,7 @@ configure_splinter_port(struct port *port) vlandev = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); - realdev_name = ovsrec_port_get_other_config_value(port->cfg, - "realdev", NULL); + realdev_name = smap_get(&port->cfg->other_config, "realdev"); realdev = iface_lookup(port->bridge, realdev_name); realdev_ofp_port = realdev ? realdev->ofp_port : 0; @@ -3880,22 +3877,21 @@ synthesize_splinter_port(const char *real_dev_name, struct ovsrec_interface *iface; struct ovsrec_port *port; - iface = xzalloc(sizeof *iface); + iface = xmalloc(sizeof *iface); + ovsrec_interface_init(iface); iface->name = xstrdup(vlan_dev_name); iface->type = "system"; - port = xzalloc(sizeof *port); + 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; - port->key_other_config = xmalloc(sizeof *port->key_other_config); - port->key_other_config[0] = "realdev"; - port->value_other_config = xmalloc(sizeof *port->value_other_config); - port->value_other_config[0] = xstrdup(real_dev_name); - port->n_other_config = 1; + + smap_add(&port->other_config, "realdev", real_dev_name); register_rec(port); return port;