X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vswitchd%2Fbridge.c;h=a11e646965c7ed217f665a50f544e9930f34c068;hb=7061a497b10b0c830cebcd463ceac053ba81dea5;hp=3bdb5db5318cc3fbdd8aeb2b1cff9e546d5c3166;hpb=40358701d5d7c8994b36260ed539a4d9c6d20cfe;p=sliver-openvswitch.git diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 3bdb5db53..a11e64696 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -18,6 +18,7 @@ #include #include #include +#include "async-append.h" #include "bfd.h" #include "bitmap.h" #include "bond.h" @@ -67,13 +68,13 @@ 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. */ + ofp_port_t ofport; /* Requested OpenFlow port number. */ }; /* OpenFlow port slated for removal from ofproto. */ struct ofpp_garbage { struct list list_node; /* Node in bridge's ofpp_garbage. */ - uint16_t ofp_port; /* Port to be deleted. */ + ofp_port_t ofp_port; /* Port to be deleted. */ }; struct iface { @@ -86,7 +87,8 @@ struct iface { /* These members are valid only after bridge_reconfigure() causes them to * be initialized. */ struct hmap_node ofp_port_node; /* In struct bridge's "ifaces" hmap. */ - int ofp_port; /* OpenFlow port number, -1 if unknown. */ + ofp_port_t ofp_port; /* OpenFlow port number, */ + /* OFPP_NONE if unknown. */ struct netdev *netdev; /* Network device. */ const char *type; /* Usually same as cfg->type. */ const struct ovsrec_interface *cfg; @@ -195,8 +197,8 @@ static size_t bridge_get_controllers(const struct bridge *br, static void bridge_add_del_ports(struct bridge *, const unsigned long int *splinter_vlans); static void bridge_refresh_ofp_port(struct bridge *); +static void bridge_configure_flow_miss_model(const char *opt); 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_table(struct bridge *); @@ -245,7 +247,8 @@ static bool mirror_configure(struct mirror *); 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_create(struct bridge *, struct if_cfg *, + ofp_port_t 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 *, @@ -255,9 +258,9 @@ static struct iface *iface_lookup(const struct bridge *, const char *name); static struct iface *iface_find(const char *name); static struct if_cfg *if_cfg_lookup(const struct bridge *, const char *name); static struct iface *iface_from_ofp_port(const struct bridge *, - uint16_t ofp_port); + ofp_port_t ofp_port); static void iface_set_mac(struct iface *); -static void iface_set_ofport(const struct ovsrec_interface *, int64_t ofport); +static void iface_set_ofport(const struct ovsrec_interface *, ofp_port_t ofport); static void iface_clear_db_record(const struct ovsrec_interface *if_cfg); static void iface_configure_qos(struct iface *, const struct ovsrec_qos *); static void iface_configure_cfm(struct iface *); @@ -265,7 +268,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 *); +static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *); /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * @@ -365,6 +368,7 @@ bridge_init(const char *remote) ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_state); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_resets); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mac_in_use); + ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ifindex); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mtu); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ofport); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_statistics); @@ -494,6 +498,16 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) ovs_assert(!reconfiguring); reconfiguring = true; + ofproto_set_flow_eviction_threshold( + smap_get_int(&ovs_cfg->other_config, "flow-eviction-threshold", + OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT)); + + ofproto_set_n_handler_threads( + smap_get_int(&ovs_cfg->other_config, "n-handler-threads", 0)); + + bridge_configure_flow_miss_model(smap_get(&ovs_cfg->other_config, + "force-miss-model")); + /* Destroy "struct bridge"s, "struct port"s, and "struct iface"s according * to 'ovs_cfg' while update the "if_cfg_queue", with only very minimal * configuration otherwise. @@ -565,7 +579,7 @@ bridge_reconfigure_ofp(void) struct if_cfg *if_cfg, *next; HMAP_FOR_EACH_SAFE (if_cfg, next, hmap_node, &br->if_cfg_todo) { - iface_create(br, if_cfg, -1); + iface_create(br, if_cfg, OFPP_NONE); time_refresh(); if (time_msec() >= deadline) { return false; @@ -612,7 +626,6 @@ 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_table(br); bridge_configure_remotes(br, managers, n_managers); @@ -622,6 +635,13 @@ bridge_reconfigure_continue(const struct ovsrec_open_vswitch *ovs_cfg) bridge_configure_stp(br); bridge_configure_tables(br); bridge_configure_dp_desc(br); + + if (smap_get(&br->cfg->other_config, "flow-eviction-threshold")) { + /* XXX: Remove this warning message eventually. */ + VLOG_WARN_ONCE("As of June 2013, flow-eviction-threshold has been" + " moved to the Open_vSwitch table. Ignoring its" + " setting in the bridge table."); + } } free(managers); @@ -680,7 +700,7 @@ bridge_update_ofprotos(void) error = ofproto_port_del(br2->ofproto, ofproto_port.ofp_port); if (error) { VLOG_ERR("failed to delete port %s: %s", ofproto_port.name, - strerror(error)); + ovs_strerror(error)); } ofproto_port_destroy(&ofproto_port); } @@ -689,7 +709,7 @@ bridge_update_ofprotos(void) error = ofproto_create(br->name, br->type, &br->ofproto); if (error) { VLOG_ERR("failed to create bridge %s: %s", br->name, - strerror(error)); + ovs_strerror(error)); bridge_destroy(br); } } @@ -793,6 +813,22 @@ port_configure(struct port *port) free(s.lacp_slaves); } +static void +bridge_configure_flow_miss_model(const char *opt) +{ + enum ofproto_flow_miss_model model = OFPROTO_HANDLE_MISS_AUTO; + + if (opt) { + if (strcmp(opt, "with-facets")) { + model = OFPROTO_HANDLE_MISS_WITH_FACETS; + } else if (strcmp(opt, "without-facets")) { + model = OFPROTO_HANDLE_MISS_WITHOUT_FACETS; + } + } + + ofproto_set_flow_miss_model(model); +} + /* Pick local port hardware address and datapath ID for 'br'. */ static void bridge_configure_datapath_id(struct bridge *br) @@ -811,7 +847,7 @@ bridge_configure_datapath_id(struct bridge *br) static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "bridge %s: failed to set bridge " "Ethernet address: %s", - br->name, strerror(error)); + br->name, ovs_strerror(error)); } } memcpy(br->ea, ea, ETH_ADDR_LEN); @@ -989,6 +1025,12 @@ bridge_configure_ipfix(struct bridge *br) if (be_cfg->obs_point_id) { be_opts.obs_point_id = *be_cfg->obs_point_id; } + if (be_cfg->cache_active_timeout) { + be_opts.cache_active_timeout = *be_cfg->cache_active_timeout; + } + if (be_cfg->cache_max_flows) { + be_opts.cache_max_flows = *be_cfg->cache_max_flows; + } } if (n_fe_opts > 0) { @@ -1001,6 +1043,10 @@ bridge_configure_ipfix(struct bridge *br) sset_init(&opts->targets); sset_add_array(&opts->targets, fe_cfg->ipfix->targets, fe_cfg->ipfix->n_targets); + opts->cache_active_timeout = fe_cfg->ipfix->cache_active_timeout + ? *fe_cfg->ipfix->cache_active_timeout : 0; + opts->cache_max_flows = fe_cfg->ipfix->cache_max_flows + ? *fe_cfg->ipfix->cache_max_flows : 0; opts++; } } @@ -1267,13 +1313,14 @@ add_del_bridges(const struct ovsrec_open_vswitch *cfg) } static void -iface_set_ofp_port(struct iface *iface, int ofp_port) +iface_set_ofp_port(struct iface *iface, ofp_port_t ofp_port) { struct bridge *br = iface->port->bridge; - ovs_assert(iface->ofp_port < 0 && ofp_port >= 0); + ovs_assert(iface->ofp_port == OFPP_NONE && ofp_port != OFPP_NONE); iface->ofp_port = ofp_port; - hmap_insert(&br->ifaces, &iface->ofp_port_node, hash_int(ofp_port, 0)); + hmap_insert(&br->ifaces, &iface->ofp_port_node, + hash_ofp_port(ofp_port)); iface_set_ofport(iface->cfg, ofp_port); } @@ -1288,7 +1335,7 @@ iface_set_netdev_config(const struct ovsrec_interface *iface_cfg, error = netdev_set_config(netdev, &iface_cfg->options); if (error) { VLOG_WARN("could not configure network device %s (%s)", - iface_cfg->name, strerror(error)); + iface_cfg->name, ovs_strerror(error)); } return error; } @@ -1308,12 +1355,12 @@ bridge_refresh_one_ofp_port(struct bridge *br, { const char *name = ofproto_port->name; const char *type = ofproto_port->type; - uint16_t ofp_port = ofproto_port->ofp_port; + ofp_port_t ofp_port = ofproto_port->ofp_port; struct iface *iface = iface_lookup(br, name); if (iface) { /* Check that the name-to-number mapping is one-to-one. */ - if (iface->ofp_port >= 0) { + if (iface->ofp_port != OFPP_NONE) { VLOG_WARN("bridge %s: interface %s reported twice", br->name, name); return false; @@ -1367,7 +1414,7 @@ bridge_refresh_ofp_port(struct bridge *br) struct iface *iface; LIST_FOR_EACH (iface, port_elem, &port->ifaces) { - iface->ofp_port = -1; + iface->ofp_port = OFPP_NONE; } } @@ -1389,7 +1436,7 @@ bridge_refresh_ofp_port(struct bridge *br) struct iface *iface, *iface_next; LIST_FOR_EACH_SAFE (iface, iface_next, port_elem, &port->ifaces) { - if (iface->ofp_port < 0) { + if (iface->ofp_port == OFPP_NONE) { bridge_queue_if_cfg(br, iface->cfg, port->cfg); iface_destroy(iface); } @@ -1402,7 +1449,7 @@ bridge_refresh_ofp_port(struct bridge *br) } /* 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 + * is OFPP_NONE, adds the network device to br->ofproto and stores the OpenFlow * port number in '*ofp_portp'; otherwise leaves br->ofproto and '*ofp_portp' * untouched. * @@ -1411,7 +1458,7 @@ bridge_refresh_ofp_port(struct bridge *br) static int iface_do_create(const struct bridge *br, const struct if_cfg *if_cfg, - int *ofp_portp, struct netdev **netdevp) + ofp_port_t *ofp_portp, struct netdev **netdevp) { const struct ovsrec_interface *iface_cfg = if_cfg->cfg; const struct ovsrec_port *port_cfg = if_cfg->parent; @@ -1429,7 +1476,7 @@ iface_do_create(const struct bridge *br, iface_get_type(iface_cfg, br->cfg), &netdev); if (error) { VLOG_WARN("could not open network device %s (%s)", - iface_cfg->name, strerror(error)); + iface_cfg->name, ovs_strerror(error)); goto error; } @@ -1438,8 +1485,8 @@ iface_do_create(const struct bridge *br, goto error; } - if (*ofp_portp < 0) { - uint16_t ofp_port = if_cfg->ofport; + if (*ofp_portp == OFPP_NONE) { + ofp_port_t ofp_port = if_cfg->ofport; error = ofproto_port_add(br->ofproto, netdev, &ofp_port); if (error) { @@ -1469,13 +1516,13 @@ error: } /* Creates a new iface on 'br' based on 'if_cfg'. The new iface has OpenFlow - * port number 'ofp_port'. If ofp_port is negative, an OpenFlow port is + * port number 'ofp_port'. If ofp_port is OFPP_NONE, an OpenFlow port is * automatically allocated for the iface. Takes ownership of and * deallocates 'if_cfg'. * * Return true if an iface is successfully created, false otherwise. */ static bool -iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) +iface_create(struct bridge *br, struct if_cfg *if_cfg, ofp_port_t ofp_port) { const struct ovsrec_interface *iface_cfg = if_cfg->cfg; const struct ovsrec_port *port_cfg = if_cfg->parent; @@ -1496,7 +1543,7 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) error = iface_do_create(br, if_cfg, &ofp_port, &netdev); bridge_run_fast(); if (error) { - iface_set_ofport(iface_cfg, -1); + iface_set_ofport(iface_cfg, OFPP_NONE); iface_clear_db_record(iface_cfg); ok = false; goto done; @@ -1515,7 +1562,7 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) hash_string(iface_cfg->name, 0)); iface->port = port; iface->name = xstrdup(iface_cfg->name); - iface->ofp_port = -1; + iface->ofp_port = OFPP_NONE; iface->netdev = netdev; iface->type = iface_get_type(iface_cfg, br->cfg); iface->cfg = iface_cfg; @@ -1537,13 +1584,13 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, int ofp_port) error = netdev_open(port->name, "internal", &netdev); if (!error) { - uint16_t fake_ofp_port = if_cfg->ofport; + ofp_port_t fake_ofp_port = if_cfg->ofport; ofproto_port_add(br->ofproto, netdev, &fake_ofp_port); netdev_close(netdev); } else { VLOG_WARN("could not open network device %s (%s)", - port->name, strerror(error)); + port->name, ovs_strerror(error)); } } else { /* Already exists, nothing to do. */ @@ -1558,23 +1605,6 @@ done: return ok; } -/* Set Flow eviction threshold */ -static void -bridge_configure_flow_eviction_threshold(struct bridge *br) -{ - const char *threshold_str; - unsigned threshold; - - threshold_str = smap_get(&br->cfg->other_config, - "flow-eviction-threshold"); - if (threshold_str) { - threshold = strtoul(threshold_str, NULL, 10); - } else { - threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_DEFAULT; - } - ofproto_set_flow_eviction_threshold(br->ofproto, threshold); -} - /* Set forward BPDU option. */ static void bridge_configure_forward_bpdu(struct bridge *br) @@ -1795,6 +1825,7 @@ iface_refresh_status(struct iface *iface) int mtu; int64_t mtu_64; uint8_t mac[ETH_ADDR_LEN]; + int64_t ifindex64; int error; if (iface_is_synthetic(iface)) { @@ -1840,6 +1871,14 @@ iface_refresh_status(struct iface *iface) } else { ovsrec_interface_set_mac_in_use(iface->cfg, NULL); } + + /* The netdev may return a negative number (such as -EOPNOTSUPP) + * if there is no valid ifindex number. */ + ifindex64 = netdev_get_ifindex(iface->netdev); + if (ifindex64 < 0) { + ifindex64 = 0; + } + ovsrec_interface_set_ifindex(iface->cfg, &ifindex64, 1); } /* Writes 'iface''s CFM statistics to the database. 'iface' must not be @@ -1889,6 +1928,8 @@ iface_refresh_cfm_stats(struct iface *iface) } else { ovsrec_interface_set_cfm_health(cfg, NULL, 0); } + + free(status.rmps); } } @@ -2419,6 +2460,8 @@ bridge_run(void) * process that forked us to exit successfully. */ daemonize_complete(); + vlog_enable_async(); + VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION); } } @@ -2551,7 +2594,7 @@ qos_unixctl_show_cb(unsigned int queue_id, } } else { ds_put_format(ds, "\tFailed to get statistics for queue %u: %s", - queue_id, strerror(error)); + queue_id, ovs_strerror(error)); } } @@ -2587,7 +2630,8 @@ qos_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, error = netdev_dump_queues(iface->netdev, qos_unixctl_show_cb, &data); if (error) { - ds_put_format(&ds, "failed to dump queues: %s", strerror(error)); + ds_put_format(&ds, "failed to dump queues: %s", + ovs_strerror(error)); } unixctl_command_reply(conn, ds_cstr(&ds)); } else { @@ -3298,7 +3342,7 @@ iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s) key = smap_get_int(&iface->cfg->other_config, "lacp-aggregation-key", 0); if (portid <= 0 || portid > UINT16_MAX) { - portid = iface->ofp_port; + portid = ofp_to_u16(iface->ofp_port); } if (priority <= 0 || priority > UINT16_MAX) { @@ -3422,11 +3466,11 @@ iface_destroy(struct iface *iface) struct port *port = iface->port; struct bridge *br = port->bridge; - if (br->ofproto && iface->ofp_port >= 0) { + if (br->ofproto && iface->ofp_port != OFPP_NONE) { ofproto_port_unregister(br->ofproto, iface->ofp_port); } - if (iface->ofp_port >= 0) { + if (iface->ofp_port != OFPP_NONE) { hmap_remove(&br->ifaces, &iface->ofp_port_node); } @@ -3486,12 +3530,12 @@ if_cfg_lookup(const struct bridge *br, const char *name) } static struct iface * -iface_from_ofp_port(const struct bridge *br, uint16_t ofp_port) +iface_from_ofp_port(const struct bridge *br, ofp_port_t ofp_port) { struct iface *iface; - HMAP_FOR_EACH_IN_BUCKET (iface, ofp_port_node, - hash_int(ofp_port, 0), &br->ifaces) { + HMAP_FOR_EACH_IN_BUCKET (iface, ofp_port_node, hash_ofp_port(ofp_port), + &br->ifaces) { if (iface->ofp_port == ofp_port) { return iface; } @@ -3519,7 +3563,7 @@ iface_set_mac(struct iface *iface) int error = netdev_set_etheraddr(iface->netdev, ea); if (error) { VLOG_ERR("interface %s: setting MAC failed (%s)", - iface->name, strerror(error)); + iface->name, ovs_strerror(error)); } } } @@ -3527,10 +3571,12 @@ iface_set_mac(struct iface *iface) /* Sets the ofport column of 'if_cfg' to 'ofport'. */ static void -iface_set_ofport(const struct ovsrec_interface *if_cfg, int64_t ofport) +iface_set_ofport(const struct ovsrec_interface *if_cfg, ofp_port_t ofport) { + int64_t port_; + port_ = (ofport == OFPP_NONE) ? -1 : ofp_to_u16(ofport); if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) { - ovsrec_interface_set_ofport(if_cfg, &ofport, 1); + ovsrec_interface_set_ofport(if_cfg, &port_, 1); } } @@ -3555,6 +3601,7 @@ iface_clear_db_record(const struct ovsrec_interface *if_cfg) ovsrec_interface_set_cfm_remote_mpids(if_cfg, NULL, 0); ovsrec_interface_set_lacp_current(if_cfg, NULL, 0); ovsrec_interface_set_statistics(if_cfg, NULL, NULL, 0); + ovsrec_interface_set_ifindex(if_cfg, NULL, 0); } } @@ -3636,7 +3683,7 @@ iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos) } } - if (iface->ofp_port >= 0) { + if (iface->ofp_port != OFPP_NONE) { const struct ofproto_port_queue *port_queues = queues_buf.data; size_t n_queues = queues_buf.size / sizeof *port_queues; @@ -3714,11 +3761,13 @@ iface_is_synthetic(const struct iface *iface) return ovsdb_idl_row_is_synthetic(&iface->cfg->header_); } -static int64_t +static ofp_port_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; + ofp_port_t ofport = cfg->n_ofport ? u16_to_ofp(*cfg->ofport) + : OFPP_NONE; + return cfg->n_ofport_request ? u16_to_ofp(*cfg->ofport_request) + : ofport; } @@ -4056,10 +4105,10 @@ collect_splinter_vlans(const struct ovsrec_open_vswitch *ovs_cfg) if (!netdev_open(vlan_dev->name, "system", &netdev)) { if (!netdev_get_in4(netdev, NULL, NULL) || !netdev_get_in6(netdev, NULL)) { - vlandev_del(vlan_dev->name); - } else { /* 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); } @@ -4096,7 +4145,7 @@ static void configure_splinter_port(struct port *port) { struct ofproto *ofproto = port->bridge->ofproto; - uint16_t realdev_ofp_port; + ofp_port_t realdev_ofp_port; const char *realdev_name; struct iface *vlandev, *realdev;