X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=36e7213a99a85953f71f44cc068aa722c06a962d;hb=b2fda3effc787f265b5ad5dfa967ac00627bd075;hp=aefaf59d0cacb99bacfc89a7ce2a92d36aef1f86;hpb=78bd1cd00123f479b6b4affd999c29fd0a6f4884;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index aefaf59d0..36e7213a9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -43,6 +43,7 @@ #include "ofproto-sflow.h" #include "poll-loop.h" #include "timer.h" +#include "unaligned.h" #include "unixctl.h" #include "vlan-bitmap.h" #include "vlog.h" @@ -170,11 +171,6 @@ struct action_xlate_ctx { * calling action_xlate_ctx_init(). */ void (*resubmit_hook)(struct action_xlate_ctx *, struct rule_dpif *); - /* If true, the speciality of 'flow' should be checked before executing - * its actions. If special_cb returns false on 'flow' rendered - * uninstallable and no actions will be executed. */ - bool check_special; - /* xlate_actions() initializes and uses these members. The client might want * to look at them after it returns. */ @@ -288,6 +284,7 @@ struct ofport_dpif { struct list bundle_node; /* In struct ofbundle's "ports" list. */ struct cfm *cfm; /* Connectivity Fault Management, if any. */ tag_type tag; /* Tag associated with this port. */ + uint32_t bond_stable_id; /* stable_id to use as bond slave, or 0. */ }; static struct ofport_dpif * @@ -307,6 +304,9 @@ struct ofproto_dpif { struct dpif *dpif; int max_ports; + /* Statistics. */ + uint64_t n_matches; + /* Bridging. */ struct netflow *netflow; struct ofproto_sflow *sflow; @@ -351,8 +351,7 @@ static void handle_upcall(struct ofproto_dpif *, struct dpif_upcall *); static int expire(struct ofproto_dpif *); /* Utilities. */ -static int send_packet(struct ofproto_dpif *, - uint32_t odp_port, uint16_t vlan_tci, +static int send_packet(struct ofproto_dpif *, uint32_t odp_port, const struct ofpbuf *packet); /* Global variables. */ @@ -417,6 +416,7 @@ construct(struct ofproto *ofproto_) } ofproto->max_ports = dpif_get_max_ports(ofproto->dpif); + ofproto->n_matches = 0; error = dpif_recv_set_mask(ofproto->dpif, ((1u << DPIF_UC_MISS) | @@ -445,6 +445,10 @@ construct(struct ofproto *ofproto_) ofproto->need_revalidate = false; tag_set_init(&ofproto->revalidate_set); + ofproto->up.tables = xmalloc(sizeof *ofproto->up.tables); + classifier_init(&ofproto->up.tables[0]); + ofproto->up.n_tables = 1; + ofproto_dpif_unixctl_init(); return 0; @@ -586,6 +590,39 @@ flush(struct ofproto *ofproto_) dpif_flow_flush(ofproto->dpif); } +static void +get_features(struct ofproto *ofproto_ OVS_UNUSED, + bool *arp_match_ip, uint32_t *actions) +{ + *arp_match_ip = true; + *actions = ((1u << OFPAT_OUTPUT) | + (1u << OFPAT_SET_VLAN_VID) | + (1u << OFPAT_SET_VLAN_PCP) | + (1u << OFPAT_STRIP_VLAN) | + (1u << OFPAT_SET_DL_SRC) | + (1u << OFPAT_SET_DL_DST) | + (1u << OFPAT_SET_NW_SRC) | + (1u << OFPAT_SET_NW_DST) | + (1u << OFPAT_SET_NW_TOS) | + (1u << OFPAT_SET_TP_SRC) | + (1u << OFPAT_SET_TP_DST) | + (1u << OFPAT_ENQUEUE)); +} + +static void +get_tables(struct ofproto *ofproto_, struct ofp_table_stats *ots) +{ + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); + struct odp_stats s; + + strcpy(ots->name, "classifier"); + + dpif_get_dp_stats(ofproto->dpif, &s); + put_32aligned_be64(&ots->lookup_count, htonll(s.n_hit + s.n_missed)); + put_32aligned_be64(&ots->matched_count, + htonll(s.n_hit + ofproto->n_matches)); +} + static int set_netflow(struct ofproto *ofproto_, const struct netflow_options *netflow_options) @@ -792,6 +829,8 @@ bundle_del_port(struct ofport_dpif *port) { struct ofbundle *bundle = port->bundle; + bundle->ofproto->need_revalidate = true; + list_remove(&port->bundle_node); port->bundle = NULL; @@ -812,7 +851,8 @@ bundle_del_port(struct ofport_dpif *port) static bool bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port, - struct lacp_slave_settings *lacp) + struct lacp_slave_settings *lacp, + uint32_t bond_stable_id) { struct ofport_dpif *port; @@ -822,6 +862,7 @@ bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port, } if (port->bundle != bundle) { + bundle->ofproto->need_revalidate = true; if (port->bundle) { bundle_del_port(port); } @@ -836,6 +877,8 @@ bundle_add_port(struct ofbundle *bundle, uint32_t ofp_port, lacp_slave_register(bundle->lacp, port, lacp); } + port->bond_stable_id = bond_stable_id; + return true; } @@ -939,7 +982,8 @@ bundle_set(struct ofproto *ofproto_, void *aux, ok = true; for (i = 0; i < s->n_slaves; i++) { if (!bundle_add_port(bundle, s->slaves[i], - s->lacp ? &s->lacp_slaves[i] : NULL)) { + s->lacp ? &s->lacp_slaves[i] : NULL, + s->bond_stable_ids ? s->bond_stable_ids[i] : 0)) { ok = false; } } @@ -948,7 +992,7 @@ bundle_set(struct ofproto *ofproto_, void *aux, LIST_FOR_EACH_SAFE (port, next_port, bundle_node, &bundle->ports) { for (i = 0; i < s->n_slaves; i++) { - if (s->slaves[i] == odp_port_to_ofp_port(port->odp_port)) { + if (s->slaves[i] == port->up.ofp_port) { goto found; } } @@ -987,13 +1031,11 @@ bundle_set(struct ofproto *ofproto_, void *aux, } } else { bundle->bond = bond_create(s->bond); + ofproto->need_revalidate = true; } LIST_FOR_EACH (port, bundle_node, &bundle->ports) { - uint16_t stable_id = (bundle->lacp - ? lacp_slave_get_port_id(bundle->lacp, port) - : port->odp_port); - bond_slave_register(bundle->bond, port, stable_id, + bond_slave_register(bundle->bond, port, port->bond_stable_id, port->up.netdev); } } else { @@ -1314,7 +1356,8 @@ is_mirror_output_bundle(struct ofproto *ofproto_, void *aux) static struct ofport_dpif * get_ofp_port(struct ofproto_dpif *ofproto, uint16_t ofp_port) { - return ofport_dpif_cast(ofproto_get_port(&ofproto->up, ofp_port)); + struct ofport *ofport = ofproto_get_port(&ofproto->up, ofp_port); + return ofport ? ofport_dpif_cast(ofport) : NULL; } static struct ofport_dpif * @@ -1347,7 +1390,7 @@ port_run(struct ofport_dpif *ofport) ETH_TYPE_CFM, sizeof *ccm); cfm_compose_ccm(ofport->cfm, ccm); send_packet(ofproto_dpif_cast(ofport->up.ofproto), - ofport->odp_port, 0, &packet); + ofport->odp_port, &packet); ofpbuf_uninit(&packet); } } @@ -1540,13 +1583,14 @@ handle_miss_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall) /* Handle 802.1ag and LACP. */ if (process_special(ofproto, &flow, upcall->packet)) { ofpbuf_delete(upcall->packet); + ofproto->n_matches++; return; } /* Check with in-band control to see if this packet should be sent * to the local port regardless of the flow table. */ if (connmgr_msg_in_hook(ofproto->up.connmgr, &flow, upcall->packet)) { - send_packet(ofproto, OFPP_LOCAL, 0, upcall->packet); + send_packet(ofproto, OFPP_LOCAL, upcall->packet); } facet = facet_lookup_valid(ofproto, &flow); @@ -1594,6 +1638,7 @@ handle_miss_upcall(struct ofproto_dpif *ofproto, struct dpif_upcall *upcall) facet_execute(ofproto, facet, upcall->packet); facet_install(ofproto, facet, false); + ofproto->n_matches++; } static void @@ -1655,7 +1700,7 @@ expire(struct ofproto_dpif *ofproto) expire_facets(ofproto, dp_max_idle); /* Expire OpenFlow flows whose idle_timeout or hard_timeout has passed. */ - cls_cursor_init(&cursor, &ofproto->up.cls, NULL); + cls_cursor_init(&cursor, &ofproto->up.tables[0], NULL); CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, up.cr, &cursor) { rule_expire(rule); } @@ -2427,7 +2472,9 @@ flow_push_stats(const struct rule_dpif *rule, static struct rule_dpif * rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow) { - return rule_dpif_cast(ofproto_rule_lookup(&ofproto->up, flow)); + return rule_dpif_cast(rule_from_cls_rule( + classifier_lookup(&ofproto->up.tables[0], + flow))); } static struct rule * @@ -2449,7 +2496,7 @@ rule_construct(struct rule *rule_) { struct rule_dpif *rule = rule_dpif_cast(rule_); struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); - struct cls_rule *displaced_rule; + struct rule_dpif *old_rule; int error; error = validate_actions(rule->up.actions, rule->up.n_actions, @@ -2458,15 +2505,19 @@ rule_construct(struct rule *rule_) return error; } + old_rule = rule_dpif_cast(rule_from_cls_rule(classifier_find_rule_exactly( + &ofproto->up.tables[0], + &rule->up.cr))); + if (old_rule) { + ofproto_rule_destroy(&old_rule->up); + } + rule->used = rule->up.created; rule->packet_count = 0; rule->byte_count = 0; list_init(&rule->facets); + classifier_insert(&ofproto->up.tables[0], &rule->up.cr); - displaced_rule = classifier_insert(&ofproto->up.cls, &rule->up.cr); - if (displaced_rule) { - ofproto_rule_destroy(rule_from_cls_rule(displaced_rule)); - } ofproto->need_revalidate = true; return 0; @@ -2479,20 +2530,11 @@ rule_destruct(struct rule *rule_) struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); struct facet *facet, *next_facet; - ofproto->need_revalidate = true; + classifier_remove(&ofproto->up.tables[0], &rule->up.cr); LIST_FOR_EACH_SAFE (facet, next_facet, list_node, &rule->facets) { facet_revalidate(ofproto, facet); } -} - -static void -rule_remove(struct rule *rule_) -{ - struct rule_dpif *rule = rule_dpif_cast(rule_); - struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto); - ofproto->need_revalidate = true; - classifier_remove(&ofproto->up.cls, &rule->up.cr); } static void @@ -2574,23 +2616,16 @@ rule_modify_actions(struct rule *rule_, return error; } -/* Sends 'packet' out of port 'odp_port' within 'ofproto'. If 'vlan_tci' is - * zero the packet will not have any 802.1Q hader; if it is nonzero, then the - * packet will be sent with the VLAN TCI specified by 'vlan_tci & ~VLAN_CFI'. - * +/* Sends 'packet' out of port 'odp_port' within 'p'. * Returns 0 if successful, otherwise a positive errno value. */ static int -send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port, uint16_t vlan_tci, +send_packet(struct ofproto_dpif *ofproto, uint32_t odp_port, const struct ofpbuf *packet) { struct ofpbuf odp_actions; int error; ofpbuf_init(&odp_actions, 32); - if (vlan_tci != 0) { - nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_SET_DL_TCI, - ntohs(vlan_tci & ~VLAN_CFI)); - } nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, odp_port); error = dpif_execute(ofproto->dpif, odp_actions.data, odp_actions.size, packet); @@ -3073,7 +3108,6 @@ action_xlate_ctx_init(struct action_xlate_ctx *ctx, ctx->flow = *flow; ctx->packet = packet; ctx->resubmit_hook = NULL; - ctx->check_special = true; } static struct ofpbuf * @@ -3089,8 +3123,7 @@ xlate_actions(struct action_xlate_ctx *ctx, ctx->recurse = 0; ctx->last_pop_priority = -1; - if (ctx->check_special - && process_special(ctx->ofproto, &ctx->flow, ctx->packet)) { + if (process_special(ctx->ofproto, &ctx->flow, ctx->packet)) { ctx->may_set_up_flow = false; } else { do_xlate_actions(in, n_in, ctx); @@ -3489,7 +3522,7 @@ is_admissible(struct ofproto_dpif *ofproto, const struct flow *flow, /* Find the port and bundle for the received packet. */ in_port = get_ofp_port(ofproto, flow->in_port); - *in_bundlep = in_bundle = in_port->bundle; + *in_bundlep = in_bundle = in_port ? in_port->bundle : NULL; if (!in_port || !in_bundle) { /* No interface? Something fishy... */ if (have_packet) { @@ -3858,6 +3891,8 @@ const struct ofproto_class ofproto_dpif_class = { run, wait, flush, + get_features, + get_tables, port_alloc, port_construct, port_destruct, @@ -3877,7 +3912,6 @@ const struct ofproto_class ofproto_dpif_class = { rule_construct, rule_destruct, rule_dealloc, - rule_remove, rule_get_stats, rule_execute, rule_modify_actions,