X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=e571bd4e2314d2113213ca83c769c7bb16e27334;hb=998bb652ecb494af8aa38ed0ae4e653cd8dff709;hp=a9e270b9fc0012c3e1efbd1f78e641b525e4b0bf;hpb=9dbb9d5e94d1db5a0fb5cb3867c26d7c3d07d0c4;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index a9e270b9..e571bd4e 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -85,7 +85,7 @@ static int xlate_actions(const union ofp_action *in, size_t n_in, struct rule { struct cls_rule cr; - uint64_t flow_cookie; /* Controller-issued identifier. + uint64_t flow_cookie; /* Controller-issued identifier. (Kept in network-byte order.) */ uint16_t idle_timeout; /* In seconds from time of last use. */ uint16_t hard_timeout; /* In seconds from time of creation. */ @@ -1071,7 +1071,6 @@ ofproto_run1(struct ofproto *p) for (i = 0; i < 50; i++) { struct ofpbuf *buf; - int error; error = dpif_recv(p->dpif, &buf); if (error) { @@ -1122,7 +1121,6 @@ ofproto_run1(struct ofproto *p) retval = pvconn_accept(ofservice->pvconn, OFP_VERSION, &vconn); if (!retval) { - struct ofconn *ofconn; struct rconn *rconn; char *name; @@ -1291,7 +1289,7 @@ ofproto_add_flow(struct ofproto *p, { struct rule *rule; rule = rule_create(p, NULL, actions, n_actions, - idle_timeout >= 0 ? idle_timeout : 5 /* XXX */, + idle_timeout >= 0 ? idle_timeout : 5 /* XXX */, 0, 0, false); cls_rule_from_flow(flow, wildcards, priority, &rule->cr); rule_insert(p, rule, NULL, 0); @@ -1927,41 +1925,44 @@ rule_has_out_port(const struct rule *rule, uint16_t out_port) return false; } +/* Executes, within 'ofproto', the 'n_actions' actions in 'actions' on + * 'packet', which arrived on 'in_port'. + * + * Takes ownership of 'packet'. */ static bool execute_odp_actions(struct ofproto *ofproto, uint16_t in_port, const union odp_action *actions, size_t n_actions, - const struct ofpbuf *packet) + struct ofpbuf *packet) { - if (n_actions > 0 && actions[0].type == ODPAT_CONTROLLER) { + if (n_actions == 1 && actions[0].type == ODPAT_CONTROLLER) { /* As an optimization, avoid a round-trip from userspace to kernel to * userspace. This also avoids possibly filling up kernel packet * buffers along the way. */ - struct ofpbuf *copy; struct odp_msg *msg; - copy = ofpbuf_new(DPIF_RECV_MSG_PADDING + sizeof(struct odp_msg) - + packet->size); - ofpbuf_reserve(copy, DPIF_RECV_MSG_PADDING); - msg = ofpbuf_put_uninit(copy, sizeof *msg); + msg = ofpbuf_push_uninit(packet, sizeof *msg); msg->type = _ODPL_ACTION_NR; msg->length = sizeof(struct odp_msg) + packet->size; msg->port = in_port; msg->reserved = 0; msg->arg = actions[0].controller.arg; - ofpbuf_put(copy, packet->data, packet->size); - send_packet_in(ofproto, copy); + send_packet_in(ofproto, packet); - actions++; - n_actions--; - } + return true; + } else { + int error; - return !n_actions || !dpif_execute(ofproto->dpif, in_port, - actions, n_actions, packet); + error = dpif_execute(ofproto->dpif, in_port, + actions, n_actions, packet); + ofpbuf_delete(packet); + return !error; + } } /* Executes the actions indicated by 'rule' on 'packet', which is in flow - * 'flow' and is considered to have arrived on ODP port 'in_port'. + * 'flow' and is considered to have arrived on ODP port 'in_port'. 'packet' + * must have at least sizeof(struct ofp_packet_in) bytes of headroom. * * The flow that 'packet' actually contains does not need to actually match * 'rule'; the actions in 'rule' will be applied to it either way. Likewise, @@ -1973,15 +1974,20 @@ execute_odp_actions(struct ofproto *ofproto, uint16_t in_port, * 'packet' using rule_make_actions(). If 'rule' is a wildcard rule, or if * 'rule' is an exact-match rule but 'flow' is not the rule's flow, then this * function will compose a set of ODP actions based on 'rule''s OpenFlow - * actions and apply them to 'packet'. */ + * actions and apply them to 'packet'. + * + * Takes ownership of 'packet'. */ static void rule_execute(struct ofproto *ofproto, struct rule *rule, struct ofpbuf *packet, const flow_t *flow) { const union odp_action *actions; + struct odp_flow_stats stats; size_t n_actions; struct odp_actions a; + assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in)); + /* Grab or compose the ODP actions. * * The special case for an exact-match 'rule' where 'flow' is not the @@ -1992,6 +1998,7 @@ rule_execute(struct ofproto *ofproto, struct rule *rule, struct rule *super = rule->super ? rule->super : rule; if (xlate_actions(super->actions, super->n_actions, flow, ofproto, packet, &a, NULL, 0, NULL)) { + ofpbuf_delete(packet); return; } actions = a.actions; @@ -2002,16 +2009,21 @@ rule_execute(struct ofproto *ofproto, struct rule *rule, } /* Execute the ODP actions. */ + flow_extract_stats(flow, packet, &stats); if (execute_odp_actions(ofproto, flow->in_port, actions, n_actions, packet)) { - struct odp_flow_stats stats; - flow_extract_stats(flow, packet, &stats); update_stats(ofproto, rule, &stats); rule->used = time_msec(); netflow_flow_update_time(ofproto->netflow, &rule->nf_flow, rule->used); } } +/* Inserts 'rule' into 'p''s flow table. + * + * If 'packet' is nonnull, takes ownership of 'packet', executes 'rule''s + * actions on it and credits the statistics for sending the packet to 'rule'. + * 'packet' must have at least sizeof(struct ofp_packet_in) bytes of + * headroom. */ static void rule_insert(struct ofproto *p, struct rule *rule, struct ofpbuf *packet, uint16_t in_port) @@ -3062,14 +3074,14 @@ handle_table_stats_request(struct ofproto *p, struct ofconn *ofconn, } static void -append_port_stat(struct ofport *port, uint16_t port_no, struct ofconn *ofconn, +append_port_stat(struct ofport *port, uint16_t port_no, struct ofconn *ofconn, struct ofpbuf **msgp) { struct netdev_stats stats; struct ofp_port_stats *ops; - /* Intentionally ignore return value, since errors will set - * 'stats' to all-1s, which is correct for OpenFlow, and + /* Intentionally ignore return value, since errors will set + * 'stats' to all-1s, which is correct for OpenFlow, and * netdev_get_stats() will log errors. */ netdev_get_stats(port->netdev, &stats); @@ -3108,7 +3120,7 @@ handle_port_stats_request(struct ofproto *p, struct ofconn *ofconn, msg = start_stats_reply(osr, sizeof *ops * 16); if (psr->port_no != htons(OFPP_NONE)) { - port = port_array_get(&p->ports, + port = port_array_get(&p->ports, ofp_port_to_odp_port(ntohs(psr->port_no))); if (port) { append_port_stat(port, ntohs(psr->port_no), ofconn, &msg); @@ -3293,7 +3305,7 @@ flow_stats_ds_cb(struct cls_rule *rule_, void *cbdata_) ds_put_cstr(results, "\n"); } -/* Adds a pretty-printed description of all flows to 'results', including +/* Adds a pretty-printed description of all flows to 'results', including * those marked hidden by secchan (e.g., by in-band control). */ void ofproto_get_all_flows(struct ofproto *p, struct ds *results) @@ -3585,7 +3597,6 @@ add_flow(struct ofproto *p, struct ofconn *ofconn, } rule_insert(p, rule, packet, in_port); - ofpbuf_delete(packet); return error; } @@ -3623,7 +3634,6 @@ send_buffered_packet(struct ofproto *ofproto, struct ofconn *ofconn, flow_extract(packet, 0, in_port, &flow); rule_execute(ofproto, rule, packet, &flow); - ofpbuf_delete(packet); return 0; } @@ -4131,9 +4141,6 @@ handle_odp_miss_msg(struct ofproto *p, struct ofpbuf *packet) } } - rule_execute(p, rule, &payload, &flow); - rule_reinstall(p, rule); - if (rule->super && rule->super->cr.priority == FAIL_OPEN_PRIORITY) { /* * Extra-special case for fail-open mode. @@ -4145,10 +4152,13 @@ handle_odp_miss_msg(struct ofproto *p, struct ofpbuf *packet) * * See the top-level comment in fail-open.c for more information. */ - send_packet_in(p, packet); - } else { - ofpbuf_delete(packet); + send_packet_in(p, ofpbuf_clone_with_headroom(packet, + DPIF_RECV_MSG_PADDING)); } + + ofpbuf_pull(packet, sizeof *msg); + rule_execute(p, rule, packet, &flow); + rule_reinstall(p, rule); } static void