X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=5ab4d3a82097e40adb2a1607649093734bf98cd7;hb=47271d0d8d12c5689cd0103dc47b62913a515b36;hp=beab99ca97b832780b42028e4855114d772c71eb;hpb=b2fda3effc787f265b5ad5dfa967ac00627bd075;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index beab99ca..5ab4d3a8 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -64,7 +64,8 @@ COVERAGE_DEFINE(ofproto_update_port); static void ofport_destroy__(struct ofport *); static void ofport_destroy(struct ofport *); -static int rule_create(struct ofproto *, const struct cls_rule *, +static int rule_create(struct ofproto *, + const struct cls_rule *, uint8_t table_id, const union ofp_action *, size_t n_actions, uint16_t idle_timeout, uint16_t hard_timeout, ovs_be64 flow_cookie, bool send_flow_removed, @@ -258,7 +259,6 @@ ofproto_create(const char *datapath_name, const char *datapath_type, ofproto->sw_desc = xstrdup(DEFAULT_SW_DESC); ofproto->serial_desc = xstrdup(DEFAULT_SERIAL_DESC); ofproto->dp_desc = xstrdup(DEFAULT_DP_DESC); - ofproto->netdev_monitor = netdev_monitor_create(); hmap_init(&ofproto->ports); shash_init(&ofproto->port_by_name); ofproto->tables = NULL; @@ -432,20 +432,19 @@ ofproto_port_clear_cfm(struct ofproto *ofproto, uint16_t ofp_port) { struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); if (ofport && ofproto->ofproto_class->set_cfm) { - ofproto->ofproto_class->set_cfm(ofport, NULL, NULL, 0); + ofproto->ofproto_class->set_cfm(ofport, NULL); } } /* Configures connectivity fault management on 'ofp_port' in 'ofproto'. Takes - * basic configuration from the configuration members in 'cfm', and the set of - * remote maintenance points from the 'n_remote_mps' elements in 'remote_mps'. - * Ignores the statistics members of 'cfm'. + * basic configuration from the configuration members in 'cfm', and the remote + * maintenance point ID from remote_mpid. Ignores the statistics members of + * 'cfm'. * * This function has no effect if 'ofproto' does not have a port 'ofp_port'. */ void ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port, - const struct cfm *cfm, - const uint16_t *remote_mps, size_t n_remote_mps) + const struct cfm_settings *s) { struct ofport *ofport; int error; @@ -457,9 +456,11 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port, return; } + /* XXX: For configuration simplicity, we only support one remote_mpid + * outside of the CFM module. It's not clear if this is the correct long + * term solution or not. */ error = (ofproto->ofproto_class->set_cfm - ? ofproto->ofproto_class->set_cfm(ofport, cfm, - remote_mps, n_remote_mps) + ? ofproto->ofproto_class->set_cfm(ofport, s) : EOPNOTSUPP); if (error) { VLOG_WARN("%s: CFM configuration on port %"PRIu16" (%s) failed (%s)", @@ -468,22 +469,6 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port, } } -/* Returns the connectivity fault management object associated with 'ofp_port' - * within 'ofproto', or a null pointer if 'ofproto' does not have a port - * 'ofp_port' or if that port does not have CFM configured. The caller must - * not modify or destroy the returned object. */ -const struct cfm * -ofproto_port_get_cfm(struct ofproto *ofproto, uint16_t ofp_port) -{ - struct ofport *ofport; - const struct cfm *cfm; - - ofport = ofproto_get_port(ofproto, ofp_port); - return (ofport - && ofproto->ofproto_class->get_cfm - && !ofproto->ofproto_class->get_cfm(ofport, &cfm)) ? cfm : NULL; -} - /* Checks the status of LACP negotiation for 'ofp_port' within ofproto. * Returns 1 if LACP partner information for 'ofp_port' is up-to-date, * 0 if LACP partner information is not current (generally indicating a @@ -601,7 +586,6 @@ ofproto_destroy__(struct ofproto *ofproto) free(ofproto->sw_desc); free(ofproto->serial_desc); free(ofproto->dp_desc); - netdev_monitor_destroy(ofproto->netdev_monitor); hmap_destroy(&ofproto->ports); shash_destroy(&ofproto->port_by_name); @@ -660,6 +644,7 @@ process_port_change(struct ofproto *ofproto, int error, char *devname) int ofproto_run(struct ofproto *p) { + struct ofport *ofport; char *devname; int error; @@ -679,9 +664,13 @@ ofproto_run(struct ofproto *p) process_port_change(p, error, devname); } } - while ((error = netdev_monitor_poll(p->netdev_monitor, - &devname)) != EAGAIN) { - process_port_change(p, error, devname); + + HMAP_FOR_EACH (ofport, hmap_node, &p->ports) { + unsigned int change_seq = netdev_change_seq(ofport->netdev); + if (ofport->change_seq != change_seq) { + ofport->change_seq = change_seq; + update_port(p, netdev_get_name(ofport->netdev)); + } } connmgr_run(p->connmgr, handle_openflow); @@ -692,11 +681,18 @@ ofproto_run(struct ofproto *p) void ofproto_wait(struct ofproto *p) { + struct ofport *ofport; + p->ofproto_class->wait(p); if (p->ofproto_class->port_poll_wait) { p->ofproto_class->port_poll_wait(p); } - netdev_monitor_poll_wait(p->netdev_monitor); + + HMAP_FOR_EACH (ofport, hmap_node, &p->ports) { + if (ofport->change_seq != netdev_change_seq(ofport->netdev)) { + poll_immediate_wake(); + } + } connmgr_wait(p->connmgr); } @@ -886,7 +882,7 @@ ofproto_add_flow(struct ofproto *p, const struct cls_rule *cls_rule, const union ofp_action *actions, size_t n_actions) { struct rule *rule; - rule_create(p, cls_rule, actions, n_actions, 0, 0, 0, false, &rule); + rule_create(p, cls_rule, 0, actions, n_actions, 0, 0, 0, false, &rule); } /* Searches for a rule with matching criteria exactly equal to 'target' in @@ -1035,11 +1031,11 @@ ofport_install(struct ofproto *p, } ofport->ofproto = p; ofport->netdev = netdev; + ofport->change_seq = netdev_change_seq(netdev); ofport->opp = *opp; ofport->ofp_port = ntohs(opp->port_no); /* Add port to 'p'. */ - netdev_monitor_add(p->netdev_monitor, ofport->netdev); hmap_insert(&p->ports, &ofport->hmap_node, hash_int(ofport->ofp_port, 0)); shash_add(&p->port_by_name, netdev_name, ofport); @@ -1106,7 +1102,7 @@ ofproto_port_unregister(struct ofproto *ofproto, uint16_t ofp_port) struct ofport *port = ofproto_get_port(ofproto, ofp_port); if (port) { if (port->ofproto->ofproto_class->set_cfm) { - port->ofproto->ofproto_class->set_cfm(port, NULL, NULL, 0); + port->ofproto->ofproto_class->set_cfm(port, NULL); } if (port->ofproto->ofproto_class->bundle_remove) { port->ofproto->ofproto_class->bundle_remove(port); @@ -1120,7 +1116,6 @@ ofport_destroy__(struct ofport *port) struct ofproto *ofproto = port->ofproto; const char *name = netdev_get_name(port->netdev); - netdev_monitor_remove(ofproto->netdev_monitor, port->netdev); hmap_remove(&ofproto->ports, &port->hmap_node); shash_delete(&ofproto->port_by_name, shash_find(&ofproto->port_by_name, name)); @@ -1179,9 +1174,8 @@ update_port(struct ofproto *ofproto, const char *name) /* Install the newly opened netdev in case it has changed. * Don't close the old netdev yet in case port_modified has to * remove a retained reference to it.*/ - netdev_monitor_remove(ofproto->netdev_monitor, port->netdev); - netdev_monitor_add(ofproto->netdev_monitor, netdev); port->netdev = netdev; + port->change_seq = netdev_change_seq(netdev); if (port->ofproto->ofproto_class->port_modified) { port->ofproto->ofproto_class->port_modified(port); @@ -1237,7 +1231,8 @@ init_ports(struct ofproto *p) * flow table, and stores the new rule into '*rulep'. Returns 0 on success, * otherwise a positive errno value or OpenFlow error code. */ static int -rule_create(struct ofproto *ofproto, const struct cls_rule *cls_rule, +rule_create(struct ofproto *ofproto, + const struct cls_rule *cls_rule, uint8_t table_id, const union ofp_action *actions, size_t n_actions, uint16_t idle_timeout, uint16_t hard_timeout, ovs_be64 flow_cookie, bool send_flow_removed, @@ -1246,6 +1241,20 @@ rule_create(struct ofproto *ofproto, const struct cls_rule *cls_rule, struct rule *rule; int error; + if (table_id == 0xff) { + if (ofproto->n_tables > 1) { + error = ofproto->ofproto_class->rule_choose_table(ofproto, + cls_rule, + &table_id); + if (error) { + return error; + } + assert(table_id < ofproto->n_tables); + } else { + table_id = 0; + } + } + rule = ofproto->ofproto_class->rule_alloc(); if (!rule) { error = ENOMEM; @@ -1254,6 +1263,7 @@ rule_create(struct ofproto *ofproto, const struct cls_rule *cls_rule, rule->ofproto = ofproto; rule->cr = *cls_rule; + rule->table_id = table_id; rule->flow_cookie = flow_cookie; rule->created = time_msec(); rule->idle_timeout = idle_timeout; @@ -1678,7 +1688,7 @@ handle_table_stats_request(struct ofconn *ofconn, ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables); for (i = 0; i < p->n_tables; i++) { ots[i].table_id = i; - sprintf(ots[i].name, "table%d", i); + sprintf(ots[i].name, "table%zu", i); ots[i].wildcards = htonl(OFPFW_ALL); ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */ ots[i].active_count = htonl(classifier_count(&p->tables[i])); @@ -2002,6 +2012,18 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto, ofproto->ofproto_class->get_netflow_ids(ofproto, engine_type, engine_id); } +/* Checks the fault status of CFM for 'ofp_port' within 'ofproto'. Returns 1 + * if CFM is faulted (generally indiciating a connectivity problem), 0 if CFM + * is not faulted, and -1 if CFM is not enabled on 'ofp_port'. */ +int +ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port) +{ + struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); + return (ofport && ofproto->ofproto_class->get_cfm_fault + ? ofproto->ofproto_class->get_cfm_fault(ofport) + : -1); +} + static void query_aggregate_stats(struct ofproto *ofproto, struct cls_rule *target, ovs_be16 out_port, uint8_t table_id, @@ -2212,7 +2234,7 @@ add_flow(struct ofconn *ofconn, struct flow_mod *fm) } buf_err = ofconn_pktbuf_retrieve(ofconn, fm->buffer_id, &packet, &in_port); - error = rule_create(p, &fm->cr, fm->actions, fm->n_actions, + error = rule_create(p, &fm->cr, fm->table_id, fm->actions, fm->n_actions, fm->idle_timeout, fm->hard_timeout, fm->cookie, fm->flags & OFPFF_SEND_FLOW_REM, &rule); if (error) {