Please review this version. Ethan
On Thu, Dec 29, 2011 at 16:05, Ethan Jackson <et...@nicira.com> wrote: > The new PACKET_IN format implemented in this patch includes flow > metadata such as the cookie, table_id, and registers. > > Signed-off-by: Ethan Jackson <et...@nicira.com> > --- > include/openflow/nicira-ext.h | 46 +++++++++++++- > lib/learning-switch.c | 2 + > lib/nx-match.h | 2 +- > lib/ofp-print.c | 34 ++++++++++ > lib/ofp-util.c | 143 > ++++++++++++++++++++++++++++++++++++++--- > lib/ofp-util.h | 16 ++++- > ofproto/connmgr.c | 25 +++++++- > ofproto/connmgr.h | 3 + > ofproto/ofproto-dpif.c | 43 ++++++++++--- > ofproto/ofproto.c | 27 ++++++++ > ofproto/pktbuf.h | 2 +- > tests/ofproto-dpif.at | 72 ++++++++++---------- > utilities/ovs-ofctl.8.in | 20 ++++++ > utilities/ovs-ofctl.c | 30 +++++++++ > 14 files changed, 405 insertions(+), 60 deletions(-) > > diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h > index 1dcd32b..f511c6c 100644 > --- a/include/openflow/nicira-ext.h > +++ b/include/openflow/nicira-ext.h > @@ -162,7 +162,12 @@ enum nicira_type { > /* Use the upper 8 bits of the 'command' member in struct ofp_flow_mod to > * designate the table to which a flow is to be added? See the big > comment > * on struct nxt_flow_mod_table_id for more information. */ > - NXT_FLOW_MOD_TABLE_ID = 15 > + NXT_FLOW_MOD_TABLE_ID = 15, > + > + > + NXT_SET_PACKET_IN_FORMAT = 16, /* Set Packet In format. */ > + NXT_PACKET_IN = 17 /* Nicira Packet In. */ > + > }; > > /* Header for Nicira vendor stats request and reply messages. */ > @@ -246,6 +251,45 @@ struct nxt_flow_mod_table_id { > }; > OFP_ASSERT(sizeof(struct nxt_flow_mod_table_id) == 24); > > +enum nx_packet_in_format{ > + NXPIF_OPENFLOW10 = 0, /* Standard OpenFlow 1.0 compatible. */ > + NXPIF_NXM = 1 /* Nicira Extended. */ > +}; > + > +/* NXT_SET_PACKET_IN_FORMAT request. */ > +struct nxt_set_packet_in_format { > + struct nicira_header nxh; > + ovs_be32 format; /* One of NXPIF_*. */ > + uint8_t pad[4]; > +}; > +OFP_ASSERT(sizeof(struct nxt_set_packet_in_format) == 24); > + > +/* NXT_PACKET_IN (analogous to OFPT_PACKET_IN). */ > +struct nxt_packet_in { > + struct nicira_header nxh; > + ovs_be32 buffer_id; /* ID assigned by datapath. */ > + ovs_be16 total_len; /* Full length of frame. */ > + uint8_t reason; /* Reason packet is sent (one of OFPR_*). */ > + uint8_t table_id; /* ID of the table that was looked up. */ > + ovs_be64 cookie; /* Cookie of the rule that was looked up. */ > + ovs_be16 match_len; /* Size of nx_match. */ > + uint8_t pad[6]; /* Align to 64-bits. */ > + /* Followed by: > + * - Exactly match_len (possibly 0) bytes containing the nx_match, then > + * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of > + * all-zero bytes, then > + * - Exactly 2 all-zero padding bytes, then > + * - An Ethernet frame whose length is inferred from nxh.header.length. > + * > + * The padding bytes preceding the Ethernet frame ensure that the IP > + * header (if any) following the Ethernet header is 32-bit aligned. */ > + > + /* uint8_t nxm_fields[...]; */ /* Match. */ > + /* uint8_t pad[2]; */ /* Align to 64 bit + 16 bit. */ > + /* uint8_t data[0]; */ /* Ethernet frame. */ > +}; > +OFP_ASSERT(sizeof(struct nxt_packet_in) == 40); > + > /* Configures the "role" of the sending controller. The default role is: > * > * - Other (NX_ROLE_OTHER), which allows the controller access to all > diff --git a/lib/learning-switch.c b/lib/learning-switch.c > index ecc5509..2fc6392 100644 > --- a/lib/learning-switch.c > +++ b/lib/learning-switch.c > @@ -257,6 +257,8 @@ lswitch_process_packet(struct lswitch *sw, struct rconn > *rconn, > case OFPUTIL_NXT_ROLE_REPLY: > case OFPUTIL_NXT_FLOW_MOD_TABLE_ID: > case OFPUTIL_NXT_SET_FLOW_FORMAT: > + case OFPUTIL_NXT_SET_PACKET_IN_FORMAT: > + case OFPUTIL_NXT_PACKET_IN: > case OFPUTIL_NXT_FLOW_MOD: > case OFPUTIL_NXT_FLOW_REMOVED: > case OFPUTIL_NXST_FLOW_REQUEST: > diff --git a/lib/nx-match.h b/lib/nx-match.h > index c7ee0f8..fa4febb 100644 > --- a/lib/nx-match.h > +++ b/lib/nx-match.h > @@ -21,10 +21,10 @@ > #include <sys/types.h> > #include <netinet/in.h> > #include "openvswitch/types.h" > +#include "flow.h" > > struct cls_rule; > struct ds; > -struct flow; > struct ofpbuf; > struct nx_action_reg_load; > struct nx_action_reg_move; > diff --git a/lib/ofp-print.c b/lib/ofp-print.c > index 4c7321f..d88d9ef 100644 > --- a/lib/ofp-print.c > +++ b/lib/ofp-print.c > @@ -84,6 +84,7 @@ ofp_print_packet_in(struct ds *string, const struct > ofp_header *oh, > { > struct ofputil_packet_in pin; > int error; > + int i; > > error = ofputil_decode_packet_in(&pin, oh); > if (error) { > @@ -91,9 +92,23 @@ ofp_print_packet_in(struct ds *string, const struct > ofp_header *oh, > return; > } > > + if (pin.table_id) { > + ds_put_format(string, " table_id=%"PRIu8, pin.table_id); > + } > + > + if (pin.cookie) { > + ds_put_format(string, " cookie=0x%"PRIx64, ntohll(pin.cookie)); > + } > + > ds_put_format(string, " total_len=%"PRIu16" in_port=", pin.total_len); > ofputil_format_port(pin.in_port, string); > > + for (i = 0; i < FLOW_N_REGS; i++) { > + if (pin.regs[i]) { > + ds_put_format(string, " reg%d=0x%"PRIx32, i, pin.regs[i]); > + } > + } > + > if (pin.reason == OFPR_ACTION) { > ds_put_cstr(string, " (via action)"); > } else if (pin.reason != OFPR_NO_MATCH) { > @@ -1248,6 +1263,20 @@ ofp_print_nxt_set_flow_format(struct ds *string, > } > > static void > +ofp_print_nxt_set_packet_in_format(struct ds *string, > + const struct nxt_set_packet_in_format > *nspf) > +{ > + uint32_t format = ntohl(nspf->format); > + > + ds_put_cstr(string, " format="); > + if (ofputil_packet_in_format_is_valid(format)) { > + ds_put_cstr(string, ofputil_packet_in_format_to_string(format)); > + } else { > + ds_put_format(string, "%"PRIu32, format); > + } > +} > + > +static void > ofp_to_string__(const struct ofp_header *oh, > const struct ofputil_msg_type *type, struct ds *string, > int verbosity) > @@ -1294,6 +1323,7 @@ ofp_to_string__(const struct ofp_header *oh, > break; > > case OFPUTIL_OFPT_PACKET_IN: > + case OFPUTIL_NXT_PACKET_IN: > ofp_print_packet_in(string, msg, verbosity); > break; > > @@ -1397,6 +1427,10 @@ ofp_to_string__(const struct ofp_header *oh, > ofp_print_nxt_set_flow_format(string, msg); > break; > > + case OFPUTIL_NXT_SET_PACKET_IN_FORMAT: > + ofp_print_nxt_set_packet_in_format(string, msg); > + break; > + > case OFPUTIL_NXT_FLOW_MOD: > ofp_print_flow_mod(string, msg, code, verbosity); > break; > diff --git a/lib/ofp-util.c b/lib/ofp-util.c > index 5a7b2a5..6d73755 100644 > --- a/lib/ofp-util.c > +++ b/lib/ofp-util.c > @@ -363,6 +363,14 @@ ofputil_decode_vendor(const struct ofp_header *oh, > size_t length, > NXT_SET_FLOW_FORMAT, "NXT_SET_FLOW_FORMAT", > sizeof(struct nxt_set_flow_format), 0 }, > > + { OFPUTIL_NXT_SET_PACKET_IN_FORMAT, > + NXT_SET_PACKET_IN_FORMAT, "NXT_SET_PACKET_IN_FORMAT", > + sizeof(struct nxt_set_packet_in_format), 0 }, > + > + { OFPUTIL_NXT_PACKET_IN, > + NXT_PACKET_IN, "NXT_PACKET_IN", > + sizeof(struct nxt_packet_in), 1 }, > + > { OFPUTIL_NXT_FLOW_MOD, > NXT_FLOW_MOD, "NXT_FLOW_MOD", > sizeof(struct nx_flow_mod), 8 }, > @@ -839,6 +847,39 @@ ofputil_flow_format_from_string(const char *s) > : -1); > } > > +bool > +ofputil_packet_in_format_is_valid(enum nx_packet_in_format packet_in_format) > +{ > + switch (packet_in_format) { > + case NXPIF_OPENFLOW10: > + case NXPIF_NXM: > + return true; > + } > + > + return false; > +} > + > +const char * > +ofputil_packet_in_format_to_string(enum nx_packet_in_format packet_in_format) > +{ > + switch (packet_in_format) { > + case NXPIF_OPENFLOW10: > + return "openflow10"; > + case NXPIF_NXM: > + return "nxm"; > + default: > + NOT_REACHED(); > + } > +} > + > +int > +ofputil_packet_in_format_from_string(const char *s) > +{ > + return (!strcmp(s, "openflow10") ? NXPIF_OPENFLOW10 > + : !strcmp(s, "nxm") ? NXPIF_NXM > + : -1); > +} > + > static bool > regs_fully_wildcarded(const struct flow_wildcards *wc) > { > @@ -927,6 +968,18 @@ ofputil_make_set_flow_format(enum nx_flow_format > flow_format) > return msg; > } > > +struct ofpbuf * > +ofputil_make_set_packet_in_format(enum nx_packet_in_format packet_in_format) > +{ > + struct nxt_set_packet_in_format *spif; > + struct ofpbuf *msg; > + > + spif = make_nxmsg(sizeof *spif, NXT_SET_PACKET_IN_FORMAT, &msg); > + spif->format = htonl(packet_in_format); > + > + return msg; > +} > + > /* Returns an OpenFlow message that can be used to turn the flow_mod_table_id > * extension on or off (according to 'flow_mod_table_id'). */ > struct ofpbuf * > @@ -1563,6 +1616,38 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin, > pin->buffer_id = ntohl(opi->buffer_id); > pin->total_len = ntohs(opi->total_len); > pin->send_len = 0; > + > + pin->table_id = 0; > + pin->cookie = 0; > + memset(pin->regs, 0, sizeof pin->regs); > + } else if (code == OFPUTIL_NXT_PACKET_IN) { > + const struct nxt_packet_in *npi = (const struct nxt_packet_in *) oh; > + uint16_t total_len = ntohs(npi->total_len); > + size_t match_len = ntohs(npi->match_len); > + struct ofpbuf nx_match; > + struct cls_rule rule; > + int error; > + > + ofpbuf_use_const(&nx_match, (uint8_t *) npi + sizeof *npi, > + ROUND_UP(match_len, 8)); > + error = nx_pull_match(&nx_match, match_len, 0, &rule, NULL, NULL); > + if (error) { > + return error; > + } > + > + ofpbuf_use_const(&pin->packet, ((uint8_t *) npi > + + ntohs(npi->nxh.header.length) > + - ntohs(npi->total_len)), total_len); > + > + pin->in_port = rule.flow.in_port; > + pin->reason = npi->reason; > + pin->table_id = npi->table_id; > + pin->cookie = npi->cookie; > + memcpy(pin->regs, rule.flow.regs, sizeof pin->regs); > + > + pin->buffer_id = ntohl(npi->buffer_id); > + pin->send_len = 0; > + pin->total_len = total_len; > } else { > NOT_REACHED(); > } > @@ -1585,10 +1670,10 @@ ofputil_decode_packet_in(struct ofputil_packet_in > *pin, > * payload. */ > struct ofpbuf * > ofputil_encode_packet_in(const struct ofputil_packet_in *pin, > - struct ofpbuf *rw_packet) > + struct ofpbuf *rw_packet, > + enum nx_packet_in_format packet_in_format) > { > int total_len = pin->packet.size; > - struct ofp_packet_in opi; > > if (rw_packet) { > if (pin->send_len < rw_packet->size) { > @@ -1601,14 +1686,52 @@ ofputil_encode_packet_in(const struct > ofputil_packet_in *pin, > } > > /* Add OFPT_PACKET_IN. */ > - memset(&opi, 0, sizeof opi); > - opi.header.version = OFP_VERSION; > - opi.header.type = OFPT_PACKET_IN; > - opi.total_len = htons(total_len); > - opi.in_port = htons(pin->in_port); > - opi.reason = pin->reason; > - opi.buffer_id = htonl(pin->buffer_id); > - ofpbuf_push(rw_packet, &opi, offsetof(struct ofp_packet_in, data)); > + if (packet_in_format == NXPIF_OPENFLOW10) { > + struct ofp_packet_in opi; > + > + memset(&opi, 0, sizeof opi); > + opi.header.version = OFP_VERSION; > + opi.header.type = OFPT_PACKET_IN; > + opi.total_len = htons(total_len); > + opi.in_port = htons(pin->in_port); > + opi.reason = pin->reason; > + opi.buffer_id = htonl(pin->buffer_id); > + ofpbuf_push(rw_packet, &opi, offsetof(struct ofp_packet_in, data)); > + } else if (packet_in_format == NXPIF_NXM) { > + struct nxt_packet_in *npi; > + struct ofpbuf nx_match; > + struct cls_rule rule; > + size_t match_len; > + size_t i; > + > + ofpbuf_init(&nx_match, 0); > + cls_rule_init_catchall(&rule, 0); > + cls_rule_set_in_port(&rule, pin->in_port); > + for (i = 0; i < FLOW_N_REGS; i++) { > + cls_rule_set_reg(&rule, i, pin->regs[i]); > + } > + match_len = nx_put_match(&nx_match, &rule, 0, 0); > + > + ofpbuf_prealloc_headroom(rw_packet, sizeof *npi + nx_match.size + 2); > + ofpbuf_push_zeros(rw_packet, 2); > + ofpbuf_push(rw_packet, nx_match.data, nx_match.size); > + npi = ofpbuf_push_zeros(rw_packet, sizeof *npi); > + ofpbuf_uninit(&nx_match); > + > + npi->nxh.header.version = OFP_VERSION; > + npi->nxh.header.type = OFPT_VENDOR; > + npi->nxh.vendor = htonl(NX_VENDOR_ID); > + npi->nxh.subtype = htonl(NXT_PACKET_IN); > + > + npi->buffer_id = htonl(pin->buffer_id); > + npi->total_len = htons(total_len); > + npi->reason = pin->reason; > + npi->table_id = pin->table_id; > + npi->cookie = pin->cookie; > + npi->match_len = htons(match_len); > + } else { > + NOT_REACHED(); > + } > update_openflow_length(rw_packet); > > return rw_packet; > diff --git a/lib/ofp-util.h b/lib/ofp-util.h > index 22dc325..f1e2c9d 100644 > --- a/lib/ofp-util.h > +++ b/lib/ofp-util.h > @@ -77,6 +77,8 @@ enum ofputil_msg_code { > OFPUTIL_NXT_FLOW_MOD_TABLE_ID, > OFPUTIL_NXT_FLOW_MOD, > OFPUTIL_NXT_FLOW_REMOVED, > + OFPUTIL_NXT_SET_PACKET_IN_FORMAT, > + OFPUTIL_NXT_PACKET_IN, > > /* NXST_* stat requests. */ > OFPUTIL_NXST_FLOW_REQUEST, > @@ -124,6 +126,12 @@ enum nx_flow_format ofputil_min_flow_format(const struct > cls_rule *); > > struct ofpbuf *ofputil_make_set_flow_format(enum nx_flow_format); > > +/* PACKET_IN. */ > +bool ofputil_packet_in_format_is_valid(enum nx_packet_in_format); > +int ofputil_packet_in_format_from_string(const char *); > +const char *ofputil_packet_in_format_to_string(enum nx_packet_in_format); > +struct ofpbuf *ofputil_make_set_packet_in_format(enum nx_packet_in_format); > + > /* NXT_FLOW_MOD_TABLE_ID extension. */ > struct ofpbuf *ofputil_make_flow_mod_table_id(bool flow_mod_table_id); > > @@ -217,6 +225,9 @@ struct ofputil_packet_in { > struct ofpbuf packet; /* Const ofpbuf. */ > uint16_t in_port; > uint8_t reason; /* One of OFPR_*. */ > + uint8_t table_id; > + ovs_be64 cookie; > + uint32_t regs[FLOW_N_REGS]; > > uint32_t buffer_id; > int send_len; > @@ -226,7 +237,10 @@ struct ofputil_packet_in { > int ofputil_decode_packet_in(struct ofputil_packet_in *, > const struct ofp_header *); > struct ofpbuf *ofputil_encode_packet_in(const struct ofputil_packet_in *, > - struct ofpbuf *rw_packet); > + struct ofpbuf *rw_packet, > + enum nx_packet_in_format); > +int ofputil_decode_packet_in(struct ofputil_packet_in *pi, > + const struct ofp_header *oh); > > /* OpenFlow protocol utility functions. */ > void *make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **); > diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c > index d32f5fd..e9f842d 100644 > --- a/ofproto/connmgr.c > +++ b/ofproto/connmgr.c > @@ -48,6 +48,7 @@ struct ofconn { > struct rconn *rconn; /* OpenFlow connection. */ > enum ofconn_type type; /* Type. */ > enum nx_flow_format flow_format; /* Currently selected flow format. */ > + enum nx_packet_in_format packet_in_format; /* OFPT_PACKET_IN format. */ > bool flow_mod_table_id; /* NXT_FLOW_MOD_TABLE_ID enabled? */ > > /* Asynchronous flow table operation support. */ > @@ -769,6 +770,25 @@ ofconn_set_flow_format(struct ofconn *ofconn, enum > nx_flow_format flow_format) > ofconn->flow_format = flow_format; > } > > +/* Returns the currently configured packet in format for 'ofconn', one of > + * NXPIF_*. > + * > + * The default, if no other format has been set, is NXPIF_OPENFLOW10. */ > +enum nx_packet_in_format > +ofconn_get_packet_in_format(struct ofconn *ofconn) > +{ > + return ofconn->packet_in_format; > +} > + > +/* Sets the packet in format for 'ofconn' to 'packet_in_format' (one of > + * NXPIF_*). */ > +void > +ofconn_set_packet_in_format(struct ofconn *ofconn, > + enum nx_packet_in_format packet_in_format) > +{ > + ofconn->packet_in_format = packet_in_format; > +} > + > /* Returns true if the NXT_FLOW_MOD_TABLE_ID extension is enabled, false > * otherwise. > * > @@ -906,6 +926,7 @@ ofconn_create(struct connmgr *mgr, struct rconn *rconn, > enum ofconn_type type) > ofconn->rconn = rconn; > ofconn->type = type; > ofconn->flow_format = NXFF_OPENFLOW10; > + ofconn->packet_in_format = NXPIF_OPENFLOW10; > ofconn->flow_mod_table_id = false; > list_init(&ofconn->opgroups); > ofconn->role = NX_ROLE_OTHER; > @@ -1229,7 +1250,9 @@ schedule_packet_in(struct ofconn *ofconn, struct > ofputil_packet_in pin, > * immediately call into do_send_packet_in() or it might buffer it for a > * while (until a later call to pinsched_run()). */ > pinsched_send(ofconn->schedulers[pin.reason == OFPR_NO_MATCH ? 0 : 1], > - flow->in_port, ofputil_encode_packet_in(&pin, rw_packet), > + flow->in_port, > + ofputil_encode_packet_in(&pin, rw_packet, > + ofconn->packet_in_format), > do_send_packet_in, ofconn); > } > > diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h > index 0224352..575c4df 100644 > --- a/ofproto/connmgr.h > +++ b/ofproto/connmgr.h > @@ -85,6 +85,9 @@ void ofconn_set_role(struct ofconn *, enum nx_role); > enum nx_flow_format ofconn_get_flow_format(struct ofconn *); > void ofconn_set_flow_format(struct ofconn *, enum nx_flow_format); > > +enum nx_packet_in_format ofconn_get_packet_in_format(struct ofconn *); > +void ofconn_set_packet_in_format(struct ofconn *, enum nx_packet_in_format); > + > bool ofconn_get_flow_mod_table_id(const struct ofconn *); > void ofconn_set_flow_mod_table_id(struct ofconn *, bool enable); > > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index 9f8c88c..504e2dd 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -204,6 +204,9 @@ struct action_xlate_ctx { > * we are just revalidating. */ > bool may_learn; > > + /* Cookie of the currently matching rule, or 0. */ > + ovs_be64 cookie; > + > /* If nonnull, called just before executing a resubmit action. > * > * This is normally null so the client has to set it manually after > @@ -237,7 +240,8 @@ struct action_xlate_ctx { > > static void action_xlate_ctx_init(struct action_xlate_ctx *, > struct ofproto_dpif *, const struct flow *, > - ovs_be16 initial_tci, const struct ofpbuf > *); > + ovs_be16 initial_tci, ovs_be64 cookie, > + const struct ofpbuf *); > static struct ofpbuf *xlate_actions(struct action_xlate_ctx *, > const union ofp_action *in, size_t n_in); > > @@ -2402,10 +2406,14 @@ send_packet_in_miss(struct ofproto_dpif *ofproto, > struct ofpbuf *packet, > > pin.in_port = flow->in_port; > pin.reason = OFPR_NO_MATCH; > + pin.table_id = 0; > + pin.cookie = 0; > + > pin.buffer_id = 0; /* not yet known */ > pin.send_len = 0; /* not used for flow table misses */ > pin.total_len = packet->size; > ofpbuf_use_const(&pin.packet, packet->data, packet->size); > + memset(pin.regs, 0, sizeof pin.regs); > connmgr_send_packet_in(ofproto->up.connmgr, &pin, flow, > clone ? NULL : packet); > } > @@ -3170,7 +3178,8 @@ facet_account(struct ofproto_dpif *ofproto, struct > facet *facet) > struct action_xlate_ctx ctx; > > action_xlate_ctx_init(&ctx, ofproto, &facet->flow, > - facet->flow.vlan_tci, NULL); > + facet->flow.vlan_tci, > + facet->rule->up.flow_cookie, NULL); > ctx.may_learn = true; > ofpbuf_delete(xlate_actions(&ctx, facet->rule->up.actions, > facet->rule->up.n_actions)); > @@ -3359,7 +3368,8 @@ facet_revalidate(struct ofproto_dpif *ofproto, struct > facet *facet) > bool should_install; > > action_xlate_ctx_init(&ctx, ofproto, &facet->flow, > - subfacet->initial_tci, NULL); > + subfacet->initial_tci, > new_rule->up.flow_cookie, > + NULL); > odp_actions = xlate_actions(&ctx, new_rule->up.actions, > new_rule->up.n_actions); > actions_changed = (subfacet->actions_len != odp_actions->size > @@ -3509,7 +3519,8 @@ flow_push_stats(const struct rule_dpif *rule, > push.bytes = bytes; > push.used = used; > > - action_xlate_ctx_init(&push.ctx, ofproto, flow, flow->vlan_tci, NULL); > + action_xlate_ctx_init(&push.ctx, ofproto, flow, flow->vlan_tci, > + rule->up.flow_cookie, NULL); > push.ctx.resubmit_hook = push_resubmit; > ofpbuf_delete(xlate_actions(&push.ctx, > rule->up.actions, rule->up.n_actions)); > @@ -3649,7 +3660,7 @@ subfacet_make_actions(struct ofproto_dpif *p, struct > subfacet *subfacet, > struct action_xlate_ctx ctx; > > action_xlate_ctx_init(&ctx, p, &facet->flow, subfacet->initial_tci, > - packet); > + rule->up.flow_cookie, packet); > odp_actions = xlate_actions(&ctx, rule->up.actions, rule->up.n_actions); > facet->tags = ctx.tags; > facet->may_install = ctx.may_set_up_flow; > @@ -3927,7 +3938,8 @@ rule_execute(struct rule *rule_, const struct flow > *flow, > struct ofpbuf *odp_actions; > size_t size; > > - action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, packet); > + action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, > + rule->up.flow_cookie, packet); > odp_actions = xlate_actions(&ctx, rule->up.actions, rule->up.n_actions); > size = packet->size; > if (execute_odp_actions(ofproto, flow, odp_actions->data, > @@ -4197,8 +4209,12 @@ xlate_table_action(struct action_xlate_ctx *ctx, > } > > if (rule) { > + ovs_be64 old_cookie = ctx->cookie; > + > ctx->recurse++; > + ctx->cookie = rule->up.flow_cookie; > do_xlate_actions(rule->up.actions, rule->up.n_actions, ctx); > + ctx->cookie = old_cookie; > ctx->recurse--; > } > > @@ -4289,11 +4305,17 @@ execute_controller_action(struct action_xlate_ctx > *ctx, int len) > } > > ofpbuf_use_const(&pin.packet, packet->data, packet->size); > + > pin.in_port = ctx->flow.in_port; > pin.reason = OFPR_ACTION; > + pin.table_id = ctx->table_id; > + pin.cookie = ctx->cookie; > + > pin.buffer_id = 0; > pin.send_len = len; > pin.total_len = packet->size; > + memcpy(pin.regs, ctx->flow.regs, sizeof pin.regs); > + > connmgr_send_packet_in(ctx->ofproto->up.connmgr, &pin, &ctx->flow, > packet); > } > > @@ -4693,13 +4715,15 @@ do_xlate_actions(const union ofp_action *in, size_t > n_in, > static void > action_xlate_ctx_init(struct action_xlate_ctx *ctx, > struct ofproto_dpif *ofproto, const struct flow *flow, > - ovs_be16 initial_tci, const struct ofpbuf *packet) > + ovs_be16 initial_tci, ovs_be64 cookie, > + const struct ofpbuf *packet) > { > ctx->ofproto = ofproto; > ctx->flow = *flow; > ctx->base_flow = ctx->flow; > ctx->base_flow.tun_id = 0; > ctx->base_flow.vlan_tci = initial_tci; > + ctx->cookie = cookie; > ctx->packet = packet; > ctx->may_learn = packet != NULL; > ctx->resubmit_hook = NULL; > @@ -5481,7 +5505,7 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf > *packet, > ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); > odp_flow_key_from_flow(&key, flow); > > - action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, packet); > + action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, 0, > packet); > odp_actions = xlate_actions(&ctx, ofp_actions, n_ofp_actions); > dpif_execute(ofproto->dpif, key.data, key.size, > odp_actions->data, odp_actions->size, packet); > @@ -5771,7 +5795,8 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int > argc, const char *argv[], > > trace.result = &result; > trace.flow = flow; > - action_xlate_ctx_init(&trace.ctx, ofproto, &flow, initial_tci, > packet); > + action_xlate_ctx_init(&trace.ctx, ofproto, &flow, initial_tci, > + rule->up.flow_cookie, packet); > trace.ctx.resubmit_hook = trace_resubmit; > odp_actions = xlate_actions(&trace.ctx, > rule->up.actions, rule->up.n_actions); > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index b6f9207..98080a3 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -2863,6 +2863,29 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, > const struct ofp_header *oh) > } > > static int > +handle_nxt_set_packet_in_format(struct ofconn *ofconn, > + const struct ofp_header *oh) > +{ > + const struct nxt_set_packet_in_format *msg; > + uint32_t format; > + > + msg = (const struct nxt_set_packet_in_format *) oh; > + format = ntohl(msg->format); > + if (format != NXFF_OPENFLOW10 && format != NXPIF_NXM) { > + return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM); > + } > + > + if (format != ofconn_get_packet_in_format(ofconn) > + && ofconn_has_pending_opgroups(ofconn)) { > + /* Avoid sending async message in surpring packet in format. */ > + return OFPROTO_POSTPONE; > + } > + > + ofconn_set_packet_in_format(ofconn, format); > + return 0; > +} > + > +static int > handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh) > { > struct ofp_header *ob; > @@ -2929,6 +2952,9 @@ handle_openflow__(struct ofconn *ofconn, const struct > ofpbuf *msg) > case OFPUTIL_NXT_SET_FLOW_FORMAT: > return handle_nxt_set_flow_format(ofconn, oh); > > + case OFPUTIL_NXT_SET_PACKET_IN_FORMAT: > + return handle_nxt_set_packet_in_format(ofconn, oh); > + > case OFPUTIL_NXT_FLOW_MOD: > return handle_flow_mod(ofconn, oh); > > @@ -2972,6 +2998,7 @@ handle_openflow__(struct ofconn *ofconn, const struct > ofpbuf *msg) > case OFPUTIL_OFPST_AGGREGATE_REPLY: > case OFPUTIL_NXT_ROLE_REPLY: > case OFPUTIL_NXT_FLOW_REMOVED: > + case OFPUTIL_NXT_PACKET_IN: > case OFPUTIL_NXST_FLOW_REPLY: > case OFPUTIL_NXST_AGGREGATE_REPLY: > default: > diff --git a/ofproto/pktbuf.h b/ofproto/pktbuf.h > index 67f4973..5dc93eb 100644 > --- a/ofproto/pktbuf.h > +++ b/ofproto/pktbuf.h > @@ -26,7 +26,7 @@ int pktbuf_capacity(void); > > struct pktbuf *pktbuf_create(void); > void pktbuf_destroy(struct pktbuf *); > -uint32_t pktbuf_save(struct pktbuf *, struct ofpbuf *buffer, uint16_t > in_port); > +uint32_t pktbuf_save(struct pktbuf *, struct ofpbuf *, uint16_t in_port); > uint32_t pktbuf_get_null(void); > int pktbuf_retrieve(struct pktbuf *, uint32_t id, struct ofpbuf **bufferp, > uint16_t *in_port); > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > index f17c882..0449009 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -172,16 +172,16 @@ OVS_VSWITCHD_START([dnl > > AT_DATA([flows.txt], [dnl > cookie=0x0 dl_src=11:11:11:11:11:11 actions=controller > -cookie=0x1 dl_src=22:22:22:22:22:22 actions=controller,resubmit:80 > +cookie=0x1 dl_src=22:22:22:22:22:22 actions=controller,resubmit(80,1) > cookie=0x2 dl_src=33:33:33:33:33:33 actions=mod_vlan_vid:15,controller > > -cookie=0x3 in_port=80 actions=mod_vlan_vid:80,controller,resubmit:81 > -cookie=0x4 in_port=81 > actions=mod_dl_src:81:81:81:81:81:81,controller,resubmit:82 > -cookie=0x5 in_port=82 > actions=mod_dl_dst:82:82:82:82:82:82,controller,resubmit:83 > -cookie=0x6 in_port=83 actions=mod_nw_src:83.83.83.83,controller,resubmit:84 > -cookie=0x7 in_port=84 actions=mod_nw_dst:84.84.84.84,controller,resubmit:85 > -cookie=0x8 in_port=85 actions=mod_tp_src:85,controller,resubmit:86 > -cookie=0x9 in_port=86 actions=mod_tp_dst:86,controller,controller > +cookie=0x3 table=1 in_port=80 > actions=load:1->NXM_NX_REG0[[]],mod_vlan_vid:80,controller,resubmit(81,2) > +cookie=0x4 table=2 in_port=81 > actions=load:2->NXM_NX_REG1[[]],mod_dl_src:81:81:81:81:81:81,controller,resubmit(82,3) > +cookie=0x5 table=3 in_port=82 > actions=load:3->NXM_NX_REG2[[]],mod_dl_dst:82:82:82:82:82:82,controller,resubmit(83,4) > +cookie=0x6 table=4 in_port=83 > actions=load:4->NXM_NX_REG3[[]],mod_nw_src:83.83.83.83,controller,resubmit(84,5) > +cookie=0x7 table=5 in_port=84 > actions=load:5->NXM_NX_REG4[[]],mod_nw_dst:84.84.84.84,controller,resubmit(85,6) > +cookie=0x8 table=6 in_port=85 actions=mod_tp_src:85,controller,resubmit(86,7) > +cookie=0x9 table=7 in_port=86 actions=mod_tp_dst:86,controller,controller > ]) > AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) > > @@ -243,7 +243,7 @@ priority:0,tunnel:0,in_port:0000,tci(vlan:15,pcp:0) > mac(33:33:33:33:33:33->50:54 > ]) > > dnl Checksum TCP. > -AT_CHECK([ovs-ofctl monitor br0 65534 --detach --pidfile 2> > ofctl_monitor.log])AT_CAPTURE_FILE([ofctl_monitor.log]) > +AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --pidfile 2> > ofctl_monitor.log])AT_CAPTURE_FILE([ofctl_monitor.log]) > > for i in 1 ; do > ovs-appctl netdev-dummy/receive p1 > 'in_port(1),eth(src=22:22:22:22:22:22,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=8,dst=11)' > @@ -251,36 +251,36 @@ done > > OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > AT_CHECK([cat ofctl_monitor.log], [0], [dnl > -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 (via action) > data_len=60 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(0) > mac(22:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 in_port=1 > reg0=0x1 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(22:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->50:54:00:00:00:07) type:0800 proto:6 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) tcp_csum:0 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0 > ip(83.83.83.83->192.168.0.2) port(8->11) tcp_csum:1a03 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(8->11) tcp_csum:3205 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(85->11) tcp_csum:31b8 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:6 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(85->86) tcp_csum:316d > ]) > > dnl Checksum UDP. > -AT_CHECK([ovs-ofctl monitor br0 65534 --detach --pidfile 2> > ofctl_monitor.log])AT_CAPTURE_FILE([ofctl_monitor.log]) > +AT_CHECK([ovs-ofctl monitor br0 65534 -P nxm --detach --pidfile 2> > ofctl_monitor.log])AT_CAPTURE_FILE([ofctl_monitor.log]) > > for i in 1 ; do > ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 22 22 22 22 22 22 > 08 00 45 00 00 1C 00 00 00 00 00 11 00 00 C0 A8 00 01 C0 A8 00 02 00 08 00 0B > 00 00 12 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' > @@ -288,45 +288,45 @@ done > > OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > AT_CHECK([cat ofctl_monitor.log], [0], [dnl > -OFPT_PACKET_IN (xid=0x0): total_len=60 in_port=1 (via action) data_len=60 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=60 in_port=1 (via action) > data_len=60 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(0) > mac(22:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=64 in_port=1 > reg0=0x1 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(22:22:22:22:22:22->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->50:54:00:00:00:07) type:0800 proto:17 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0 > ip(192.168.0.1->192.168.0.2) port(8->11) udp_csum:1234 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 (via action) data_len=64 (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0 > ip(83.83.83.83->192.168.0.2) port(8->11) udp_csum:2c37 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(8->11) udp_csum:4439 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(85->11) udp_csum:43ec > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(85->86) udp_csum:43a1 > dnl > -OFPT_PACKET_IN (xid=0x0): total_len=64 in_port=1 (via action) data_len=64 > (unbuffered) > +NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=64 in_port=1 > reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=64 > (unbuffered) > priority:0,tunnel:0,in_port:0000,tci(vlan:80,pcp:0) > mac(81:81:81:81:81:81->82:82:82:82:82:82) type:0800 proto:17 tos:0 ttl:0 > ip(83.83.83.83->84.84.84.84) port(85->86) udp_csum:43a1 > ]) > > AT_CHECK([ovs-ofctl dump-flows br0 | sed > 's/duration=[[0-9]]*\.[[0-9]]*s,/duration=\<omitted\>,/' | sort], [0], [dnl > cookie=0x0, duration=<omitted>, table=0, n_packets=3, n_bytes=180, > dl_src=11:11:11:11:11:11 actions=CONTROLLER:65535 > - cookie=0x1, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > dl_src=22:22:22:22:22:22 actions=CONTROLLER:65535,resubmit:80 > + cookie=0x1, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > dl_src=22:22:22:22:22:22 actions=CONTROLLER:65535,resubmit(80,1) > cookie=0x2, duration=<omitted>, table=0, n_packets=3, n_bytes=180, > dl_src=33:33:33:33:33:33 actions=mod_vlan_vid:15,CONTROLLER:65535 > - cookie=0x3, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > in_port=80 actions=mod_vlan_vid:80,CONTROLLER:65535,resubmit:81 > - cookie=0x4, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > in_port=81 actions=mod_dl_src:81:81:81:81:81:81,CONTROLLER:65535,resubmit:82 > - cookie=0x5, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > in_port=82 actions=mod_dl_dst:82:82:82:82:82:82,CONTROLLER:65535,resubmit:83 > - cookie=0x6, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > in_port=83 actions=mod_nw_src:83.83.83.83,CONTROLLER:65535,resubmit:84 > - cookie=0x7, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > in_port=84 actions=mod_nw_dst:84.84.84.84,CONTROLLER:65535,resubmit:85 > - cookie=0x8, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > in_port=85 actions=mod_tp_src:85,CONTROLLER:65535,resubmit:86 > - cookie=0x9, duration=<omitted>, table=0, n_packets=2, n_bytes=120, > in_port=86 actions=mod_tp_dst:86,CONTROLLER:65535,CONTROLLER:65535 > + cookie=0x3, duration=<omitted>, table=1, n_packets=2, n_bytes=120, > in_port=80 > actions=load:0x1->NXM_NX_REG0[[]],mod_vlan_vid:80,CONTROLLER:65535,resubmit(81,2) > + cookie=0x4, duration=<omitted>, table=2, n_packets=2, n_bytes=120, > in_port=81 > actions=load:0x2->NXM_NX_REG1[[]],mod_dl_src:81:81:81:81:81:81,CONTROLLER:65535,resubmit(82,3) > + cookie=0x5, duration=<omitted>, table=3, n_packets=2, n_bytes=120, > in_port=82 > actions=load:0x3->NXM_NX_REG2[[]],mod_dl_dst:82:82:82:82:82:82,CONTROLLER:65535,resubmit(83,4) > + cookie=0x6, duration=<omitted>, table=4, n_packets=2, n_bytes=120, > in_port=83 > actions=load:0x4->NXM_NX_REG3[[]],mod_nw_src:83.83.83.83,CONTROLLER:65535,resubmit(84,5) > + cookie=0x7, duration=<omitted>, table=5, n_packets=2, n_bytes=120, > in_port=84 > actions=load:0x5->NXM_NX_REG4[[]],mod_nw_dst:84.84.84.84,CONTROLLER:65535,resubmit(85,6) > + cookie=0x8, duration=<omitted>, table=6, n_packets=2, n_bytes=120, > in_port=85 actions=mod_tp_src:85,CONTROLLER:65535,resubmit(86,7) > + cookie=0x9, duration=<omitted>, table=7, n_packets=2, n_bytes=120, > in_port=86 actions=mod_tp_dst:86,CONTROLLER:65535,CONTROLLER:65535 > NXST_FLOW reply (xid=0x4): > ]) > > diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in > index 6c78c68..26a4072 100644 > --- a/utilities/ovs-ofctl.8.in > +++ b/utilities/ovs-ofctl.8.in > @@ -1049,6 +1049,26 @@ above table, overrides \fBovs\-ofctl\fR's default > choice of flow > format. If a command cannot work as requested using the requested > flow format, \fBovs\-ofctl\fR will report a fatal error. > . > +. > +.IP "\fB\-P \fIformat\fR" > +.IQ "\fB\-\-packet\-in\-format=\fIformat\fR" > +\fBovs\-ofctl\fR supports the following packet_in formats, in order of > +increasing capability: > +.RS > +.IP "\fBopenflow10\fR" > +This is the standard OpenFlow 1.0 packet in format. It should be supported by > +all OpenFlow switches. > +. > +.IP "\fBnxm\fR (Nicira Extended Match)" > +This packet_in format includes flow metadata encoded using the NXM format. > +. > +.RE > +.IP > +Usually, \fBovs\-ofctl\fR allows the switch to choose its default packet_in > +format. When \fIformat\fR is one of the formats listed in the above table, > +\fBovs\-ofctl\fR will insist on the selected format. If the switch does not > +support the requested format, \fBovs\-ofctl\fR will report a fatal error. > +. > .IP "\fB\-m\fR" > .IQ "\fB\-\-more\fR" > Increases the verbosity of OpenFlow messages printed and logged by > diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c > index 15bdbee..1b5c979 100644 > --- a/utilities/ovs-ofctl.c > +++ b/utilities/ovs-ofctl.c > @@ -66,6 +66,11 @@ static bool readd; > * particular flow format or -1 to let ovs-ofctl choose intelligently. */ > static int preferred_flow_format = -1; > > +/* -P, --packet-in-format: Packet IN format to use in monitor and snoop > + * commands. Either one of NXPIF_* to force a particular packet_in format, > or > + * -1 to let ovs-ofctl choose the default. */ > +static int preferred_packet_in_format = -1; > + > /* -m, --more: Additional verbosity for ofp-print functions. */ > static int verbosity; > > @@ -98,6 +103,7 @@ parse_options(int argc, char *argv[]) > {"strict", no_argument, NULL, OPT_STRICT}, > {"readd", no_argument, NULL, OPT_READD}, > {"flow-format", required_argument, NULL, 'F'}, > + {"packet-in-format", required_argument, NULL, 'P'}, > {"more", no_argument, NULL, 'm'}, > {"help", no_argument, NULL, 'h'}, > {"version", no_argument, NULL, 'V'}, > @@ -135,6 +141,14 @@ parse_options(int argc, char *argv[]) > } > break; > > + case 'P': > + preferred_packet_in_format = > + ofputil_packet_in_format_from_string(optarg); > + if (preferred_packet_in_format < 0) { > + ovs_fatal(0, "unknown packet-in format `%s'", optarg); > + } > + break; > + > case 'm': > verbosity++; > break; > @@ -205,6 +219,7 @@ usage(void) > " --strict use strict match for flow > commands\n" > " --readd replace flows that haven't > changed\n" > " -F, --flow-format=FORMAT force particular flow format\n" > + " -P, --packet-in-format=FRMT force particular packet in > format\n" > " -m, --more be more verbose printing OpenFlow\n" > " -t, --timeout=SECS give up after SECS seconds\n" > " -h, --help display this help message\n" > @@ -766,12 +781,27 @@ do_del_flows(int argc, char *argv[]) > } > > static void > +set_packet_in_format(struct vconn *vconn, > + enum nx_packet_in_format packet_in_format) > +{ > + struct ofpbuf *spif = > ofputil_make_set_packet_in_format(packet_in_format); > + transact_noreply(vconn, spif); > + VLOG_DBG("%s: using user-specified packet in format %s", > + vconn_get_name(vconn), > + ofputil_packet_in_format_to_string(packet_in_format)); > +} > + > +static void > monitor_vconn(struct vconn *vconn) > { > struct unixctl_server *server; > bool exiting = false; > int error, fd; > > + if (preferred_packet_in_format >= 0) { > + set_packet_in_format(vconn, preferred_packet_in_format); > + } > + > /* Daemonization will close stderr but we really want to keep it, so make > a > * copy. */ > fd = dup(STDERR_FILENO); > -- > 1.7.7.1 > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev