X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=vswitchd%2Fbridge.c;h=31e6cb073452f1efca9408b85836d4aa308f6123;hb=cd11000ba2ce68a6eaeabed7efcb061b39ceaa44;hp=0cdf72f7302863bdfd065c78c514c73af857622e;hpb=8722022c0c0d29d3f998dc26c50944c456e56646;p=openvswitch diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 0cdf72f7..31e6cb07 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -36,6 +36,7 @@ #include "dynamic-string.h" #include "flow.h" #include "hash.h" +#include "jsonrpc.h" #include "list.h" #include "mac-learning.h" #include "netdev.h" @@ -158,11 +159,6 @@ struct bridge { bool sent_config_request; /* Successfully sent config request? */ uint8_t default_ea[ETH_ADDR_LEN]; /* Default MAC. */ - /* Support for remote controllers. */ - char *controller; /* NULL if there is no remote controller; - * "discover" to do controller discovery; - * otherwise a vconn name. */ - /* OpenFlow switch processing. */ struct ofproto *ofproto; /* OpenFlow switch. */ @@ -208,13 +204,15 @@ static void bridge_destroy(struct bridge *); static struct bridge *bridge_lookup(const char *name); static unixctl_cb_func bridge_unixctl_dump_flows; static int bridge_run_one(struct bridge *); -static const struct ovsrec_controller *bridge_get_controller( - const struct ovsrec_open_vswitch *ovs_cfg, - const struct bridge *br); +static size_t bridge_get_controllers(const struct ovsrec_open_vswitch *ovs_cfg, + const struct bridge *br, + struct ovsrec_controller ***controllersp); static void bridge_reconfigure_one(const struct ovsrec_open_vswitch *, struct bridge *); static void bridge_reconfigure_controller(const struct ovsrec_open_vswitch *, - struct bridge *); + struct bridge *, + const struct sockaddr_in *managers, + size_t n_managers); static void bridge_get_all_ifaces(const struct bridge *, struct shash *ifaces); static void bridge_fetch_dp_ifaces(struct bridge *); static void bridge_flush(struct bridge *); @@ -518,6 +516,44 @@ iterate_and_prune_ifaces(struct bridge *br, } } +/* Looks at the list of managers in 'ovs_cfg' and extracts their remote IP + * addresses and ports into '*managersp' and '*n_managersp'. The caller is + * responsible for freeing '*managersp' (with free()). + * + * You may be asking yourself "why does ovs-vswitchd care?", because + * ovsdb-server is responsible for connecting to the managers, and ovs-vswitchd + * should not be and in fact is not directly involved in that. But + * ovs-vswitchd needs to make sure that ovsdb-server can reach the managers, so + * it has to tell in-band control where the managers are to enable that. + */ +static void +collect_managers(const struct ovsrec_open_vswitch *ovs_cfg, + struct sockaddr_in **managersp, size_t *n_managersp) +{ + struct sockaddr_in *managers = NULL; + size_t n_managers = 0; + + if (ovs_cfg->n_managers > 0) { + size_t i; + + managers = xmalloc(ovs_cfg->n_managers * sizeof *managers); + for (i = 0; i < ovs_cfg->n_managers; i++) { + const char *name = ovs_cfg->managers[i]; + struct sockaddr_in *sin = &managers[i]; + + if ((!strncmp(name, "tcp:", 4) + && inet_parse_active(name + 4, JSONRPC_TCP_PORT, sin)) || + (!strncmp(name, "ssl:", 4) + && inet_parse_active(name + 4, JSONRPC_SSL_PORT, sin))) { + n_managers++; + } + } + } + + *managersp = managers; + *n_managersp = n_managers; +} + void bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) { @@ -525,6 +561,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) struct shash old_br, new_br; struct shash_node *node; struct bridge *br, *next; + struct sockaddr_in *managers; + size_t n_managers; size_t i; int sflow_bridge_number; @@ -532,6 +570,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) txn = ovsdb_idl_txn_create(ovs_cfg->header_.table->idl); + collect_managers(ovs_cfg, &managers, &n_managers); + /* Collect old and new bridges. */ shash_init(&old_br); shash_init(&new_br); @@ -745,8 +785,10 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) /* Set sFlow configuration on this bridge. */ if (br->cfg->sflow) { const struct ovsrec_sflow *sflow_cfg = br->cfg->sflow; - const struct ovsrec_controller *ctrl; + struct ovsrec_controller **controllers; struct ofproto_sflow_options oso; + size_t n_controllers; + size_t i; memset(&oso, 0, sizeof oso); @@ -771,8 +813,14 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) oso.sub_id = sflow_bridge_number++; oso.agent_device = sflow_cfg->agent; - ctrl = bridge_get_controller(ovs_cfg, br); - oso.control_ip = ctrl ? ctrl->local_ip : NULL; + oso.control_ip = NULL; + n_controllers = bridge_get_controllers(ovs_cfg, br, &controllers); + for (i = 0; i < n_controllers; i++) { + if (controllers[i]->local_ip) { + oso.control_ip = controllers[i]->local_ip; + break; + } + } ofproto_set_sflow(br->ofproto, &oso); svec_destroy(&oso.targets); @@ -789,7 +837,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) * yet; when a controller is configured, resetting the datapath ID will * immediately disconnect from the controller, so it's better to set * the datapath ID before the controller. */ - bridge_reconfigure_controller(ovs_cfg, br); + bridge_reconfigure_controller(ovs_cfg, br, managers, n_managers); } LIST_FOR_EACH (br, struct bridge, node, &all_bridges) { for (i = 0; i < br->n_ports; i++) { @@ -807,6 +855,8 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) ovsdb_idl_txn_commit(txn); ovsdb_idl_txn_destroy(txn); /* XXX */ + + free(managers); } static const char * @@ -1052,7 +1102,7 @@ bridge_wait(void) LIST_FOR_EACH (br, struct bridge, node, &all_bridges) { ofproto_wait(br->ofproto); - if (br->controller) { + if (ofproto_has_controller(br->ofproto)) { continue; } @@ -1182,7 +1232,6 @@ bridge_destroy(struct bridge *br) } dpif_close(br->dpif); ofproto_destroy(br->ofproto); - free(br->controller); mac_learning_destroy(br->ml); port_array_destroy(&br->ifaces); free(br->ports); @@ -1258,21 +1307,31 @@ bridge_run_one(struct bridge *br) return error; } -static const struct ovsrec_controller * -bridge_get_controller(const struct ovsrec_open_vswitch *ovs_cfg, - const struct bridge *br) +static size_t +bridge_get_controllers(const struct ovsrec_open_vswitch *ovs_cfg, + const struct bridge *br, + struct ovsrec_controller ***controllersp) { - const struct ovsrec_controller *controller; + struct ovsrec_controller **controllers; + size_t n_controllers; - controller = (br->cfg->controller ? br->cfg->controller - : ovs_cfg->controller ? ovs_cfg->controller - : NULL); + if (br->cfg->n_controller) { + controllers = br->cfg->controller; + n_controllers = br->cfg->n_controller; + } else { + controllers = ovs_cfg->controller; + n_controllers = ovs_cfg->n_controller; + } - if (controller && !strcmp(controller->target, "none")) { - return NULL; + if (n_controllers == 1 && !strcmp(controllers[0]->target, "none")) { + controllers = NULL; + n_controllers = 0; } - return controller; + if (controllersp) { + *controllersp = controllers; + } + return n_controllers; } static bool @@ -1391,7 +1450,7 @@ bridge_reconfigure_one(const struct ovsrec_open_vswitch *ovs_cfg, * user didn't specify one. * * XXX perhaps we should synthesize a port ourselves in this case. */ - if (bridge_get_controller(ovs_cfg, br)) { + if (bridge_get_controllers(ovs_cfg, br, NULL)) { char local_name[IF_NAMESIZE]; int error; @@ -1504,86 +1563,27 @@ bridge_reconfigure_one(const struct ovsrec_open_vswitch *ovs_cfg, static void bridge_reconfigure_controller(const struct ovsrec_open_vswitch *ovs_cfg, - struct bridge *br) + struct bridge *br, + const struct sockaddr_in *managers, + size_t n_managers) { - const struct ovsrec_controller *c; + struct ovsrec_controller **controllers; + size_t n_controllers; - c = bridge_get_controller(ovs_cfg, br); - if ((br->controller != NULL) != (c != NULL)) { + ofproto_set_extra_in_band_remotes(br->ofproto, managers, n_managers); + + n_controllers = bridge_get_controllers(ovs_cfg, br, &controllers); + if (ofproto_has_controller(br->ofproto) != (n_controllers != 0)) { ofproto_flush_flows(br->ofproto); } - free(br->controller); - br->controller = c ? xstrdup(c->target) : NULL; - - if (c) { - int max_backoff, probe; - int rate_limit, burst_limit; - - if (!strcmp(c->target, "discover")) { - ofproto_set_discovery(br->ofproto, true, - c->discover_accept_regex, - c->discover_update_resolv_conf); - } else { - struct iface *local_iface; - struct in_addr ip; - bool in_band; - - in_band = (!c->connection_mode - || !strcmp(c->connection_mode, "out-of-band")); - ofproto_set_discovery(br->ofproto, false, NULL, NULL); - ofproto_set_in_band(br->ofproto, in_band); - - local_iface = bridge_get_local_iface(br); - if (local_iface && c->local_ip && inet_aton(c->local_ip, &ip)) { - struct netdev *netdev = local_iface->netdev; - struct in_addr mask, gateway; - - if (!c->local_netmask || !inet_aton(c->local_netmask, &mask)) { - mask.s_addr = 0; - } - if (!c->local_gateway - || !inet_aton(c->local_gateway, &gateway)) { - gateway.s_addr = 0; - } - - netdev_turn_flags_on(netdev, NETDEV_UP, true); - if (!mask.s_addr) { - mask.s_addr = guess_netmask(ip.s_addr); - } - 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)); - } - - if (gateway.s_addr) { - if (!netdev_add_router(netdev, gateway)) { - VLOG_INFO("bridge %s: configured gateway "IP_FMT, - br->name, IP_ARGS(&gateway.s_addr)); - } - } - } - } - - ofproto_set_failure(br->ofproto, - (!c->fail_mode - || !strcmp(c->fail_mode, "standalone") - || !strcmp(c->fail_mode, "open"))); - - probe = c->inactivity_probe ? *c->inactivity_probe / 1000 : 5; - ofproto_set_probe_interval(br->ofproto, probe); - - max_backoff = c->max_backoff ? *c->max_backoff / 1000 : 8; - ofproto_set_max_backoff(br->ofproto, max_backoff); - rate_limit = c->controller_rate_limit ? *c->controller_rate_limit : 0; - burst_limit = c->controller_burst_limit ? *c->controller_burst_limit : 0; - ofproto_set_rate_limit(br->ofproto, rate_limit, burst_limit); - } else { + if (!n_controllers) { union ofp_action action; flow_t flow; + /* Clear out controllers. */ + ofproto_set_controllers(br->ofproto, NULL, 0); + /* Set up a flow that matches every packet and directs them to * OFPP_NORMAL (which goes to us). */ memset(&action, 0, sizeof action); @@ -1592,14 +1592,77 @@ bridge_reconfigure_controller(const struct ovsrec_open_vswitch *ovs_cfg, action.output.port = htons(OFPP_NORMAL); memset(&flow, 0, sizeof flow); ofproto_add_flow(br->ofproto, &flow, OVSFW_ALL, 0, &action, 1, 0); + } else { + struct ofproto_controller *ocs; + size_t i; - ofproto_set_in_band(br->ofproto, false); - ofproto_set_max_backoff(br->ofproto, 1); - ofproto_set_probe_interval(br->ofproto, 5); - ofproto_set_failure(br->ofproto, false); - } + ocs = xmalloc(n_controllers * sizeof *ocs); + for (i = 0; i < n_controllers; i++) { + struct ovsrec_controller *c = controllers[i]; + struct ofproto_controller *oc = &ocs[i]; + + if (strcmp(c->target, "discover")) { + struct iface *local_iface; + struct in_addr ip; + + local_iface = bridge_get_local_iface(br); + if (local_iface && c->local_ip + && inet_aton(c->local_ip, &ip)) { + struct netdev *netdev = local_iface->netdev; + struct in_addr mask, gateway; + + if (!c->local_netmask + || !inet_aton(c->local_netmask, &mask)) { + mask.s_addr = 0; + } + if (!c->local_gateway + || !inet_aton(c->local_gateway, &gateway)) { + gateway.s_addr = 0; + } - ofproto_set_controller(br->ofproto, br->controller); + netdev_turn_flags_on(netdev, NETDEV_UP, true); + if (!mask.s_addr) { + mask.s_addr = guess_netmask(ip.s_addr); + } + 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)); + } + + if (gateway.s_addr) { + if (!netdev_add_router(netdev, gateway)) { + VLOG_INFO("bridge %s: configured gateway "IP_FMT, + br->name, IP_ARGS(&gateway.s_addr)); + } + } + } + } + + oc->target = c->target; + oc->max_backoff = c->max_backoff ? *c->max_backoff / 1000 : 8; + oc->probe_interval = (c->inactivity_probe + ? *c->inactivity_probe / 1000 : 5); + oc->fail = (!c->fail_mode + || !strcmp(c->fail_mode, "standalone") + || !strcmp(c->fail_mode, "open") + ? OFPROTO_FAIL_STANDALONE + : OFPROTO_FAIL_SECURE); + oc->band = (!c->connection_mode + || !strcmp(c->connection_mode, "in-band") + ? OFPROTO_IN_BAND + : OFPROTO_OUT_OF_BAND); + oc->accept_re = c->discover_accept_regex; + oc->update_resolv_conf = c->discover_update_resolv_conf; + oc->rate_limit = (c->controller_rate_limit + ? *c->controller_rate_limit : 0); + oc->burst_limit = (c->controller_burst_limit + ? *c->controller_burst_limit : 0); + } + ofproto_set_controllers(br->ofproto, ocs, n_controllers); + free(ocs); + } } static void