From: Giuseppe Lettieri Date: Mon, 24 Sep 2012 13:26:21 +0000 (+0200) Subject: Merge branch 'mainstream' X-Git-Tag: sliver-openvswitch-1.8.90-0~1 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=91ae5bece01cfe69741f9e284d0ccf78fce87eb0;hp=2977805cbd34f50becafa505395ccb0735197ed7;p=sliver-openvswitch.git Merge branch 'mainstream' --- diff --git a/AUTHORS b/AUTHORS index 70257e549..1ed8676c2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,6 +6,7 @@ Alexey I. Froloff raorn@altlinux.org Andrew Evans aevans@nicira.com Andrew Lambeth wal@nicira.com Andy Southgate andy.southgate@citrix.com +Anupam Chanda achanda@nicira.com Arun Sharma arun.sharma@calsoftinc.com Ben Pfaff blp@nicira.com Brian Kruger bkruger+ovsdev@gmail.com diff --git a/FAQ b/FAQ index ae904f195..a98739cb3 100644 --- a/FAQ +++ b/FAQ @@ -740,6 +740,13 @@ A: The OFPT_FEATURES_REQUEST message requests an OpenFlow switch to normally an intermittent condition (unless ovs-vswitchd is not running). +Q: I added some flows with my controller or with ovs-ofctl, but when I + run "ovs-dpctl dump-flows" I don't see them. + +A: ovs-dpctl queries a kernel datapath, not an OpenFlow switch. It + won't display the information that you want. You want to use + "ovs-ofctl dump-flows" instead. + Contact ------- diff --git a/NEWS b/NEWS index cbc5c5862..38e512976 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,14 @@ post-v1.8.0 - OpenFlow: - Allow bitwise masking for SHA and THA fields in ARP, SLL and TLL fields in IPv6 neighbor discovery messages, and IPv6 flow label. + - ovs-ofctl: + - Commands and actions that accept port numbers now also accept keywords + that represent those ports (such as LOCAL, NONE, and ALL). This is + also the recommended way to specify these ports, for compatibility + with OpenFlow 1.1 and later (which use the OpenFlow 1.0 numbers + for these ports for different purposes). + - Commands and actions that accept port numbers no longer accept port 0, + which is not a valid port number in OpenFlow 1.0 and later. - ovs-dpctl: - Support requesting the port number with the "port_no" option in the "add-if" command. diff --git a/datapath/datapath.c b/datapath/datapath.c index c83ce1672..a6915fb2b 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -2257,3 +2257,4 @@ module_exit(dp_cleanup); MODULE_DESCRIPTION("Open vSwitch switching datapath"); MODULE_LICENSE("GPL"); +MODULE_VERSION(VERSION); diff --git a/datapath/vport.c b/datapath/vport.c index 172261aa5..dc7adfabf 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -522,7 +522,7 @@ void ovs_vport_record_error(struct vport *vport, enum vport_err_type err_type) case VPORT_E_TX_ERROR: vport->err_stats.tx_errors++; break; - }; + } spin_unlock(&vport->stats_lock); } diff --git a/include/openflow/openflow-1.0.h b/include/openflow/openflow-1.0.h index 56af4c521..9af7740f8 100644 --- a/include/openflow/openflow-1.0.h +++ b/include/openflow/openflow-1.0.h @@ -21,12 +21,20 @@ #include "openflow/openflow-common.h" -/* Port numbering. Physical ports are numbered starting from 1. */ +/* Port number(s) meaning + * --------------- -------------------------------------- + * 0x0000 not assigned a meaning by OpenFlow 1.0 + * 0x0001...0xfeff "physical" ports + * 0xff00...0xfff7 "reserved" but not assigned a meaning by OpenFlow 1.0 + * 0xfff8...0xffff "reserved" OFPP_* ports with assigned meanings + */ enum ofp_port { - /* Maximum number of physical switch ports. */ - OFPP_MAX = 0xff00, + /* Ranges. */ + OFPP_MAX = 0xff00, /* Maximum number of physical switch ports. */ + OFPP_FIRST_RESV = 0xfff8, /* First assigned reserved port number. */ + OFPP_LAST_RESV = 0xffff, /* Last assigned reserved port number. */ - /* Fake output "ports". */ + /* Reserved output "ports". */ OFPP_IN_PORT = 0xfff8, /* Send the packet out the input port. This virtual port must be explicitly used in order to send back out of the input diff --git a/include/openflow/openflow-1.1.h b/include/openflow/openflow-1.1.h index 696c3ec45..9785db456 100644 --- a/include/openflow/openflow-1.1.h +++ b/include/openflow/openflow-1.1.h @@ -281,6 +281,10 @@ enum ofp11_instruction_type { OFPIT11_EXPERIMENTER = 0xFFFF /* Experimenter instruction */ }; +#define OFPIT11_ALL (OFPIT11_GOTO_TABLE | OFPIT11_WRITE_METADATA | \ + OFPIT11_WRITE_ACTIONS | OFPIT11_APPLY_ACTIONS | \ + OFPIT11_CLEAR_ACTIONS) + #define OFP11_INSTRUCTION_ALIGN 8 /* Generic ofp_instruction structure. */ @@ -588,6 +592,26 @@ OFP_ASSERT(sizeof(struct ofp11_flow_stats) == 48); /* Body for ofp_stats_request of type OFPST_AGGREGATE. */ /* Identical to ofp11_flow_stats_request */ +/* Flow match fields. */ +enum ofp11_flow_match_fields { + OFPFMF11_IN_PORT = 1 << 0, /* Switch input port. */ + OFPFMF11_DL_VLAN = 1 << 1, /* VLAN id. */ + OFPFMF11_DL_VLAN_PCP = 1 << 2, /* VLAN priority. */ + OFPFMF11_DL_TYPE = 1 << 3, /* Ethernet frame type. */ + OFPFMF11_NW_TOS = 1 << 4, /* IP ToS (DSCP field, 6 bits). */ + OFPFMF11_NW_PROTO = 1 << 5, /* IP protocol. */ + OFPFMF11_TP_SRC = 1 << 6, /* TCP/UDP/SCTP source port. */ + OFPFMF11_TP_DST = 1 << 7, /* TCP/UDP/SCTP destination port. */ + OFPFMF11_MPLS_LABEL = 1 << 8, /* MPLS label. */ + OFPFMF11_MPLS_TC = 1 << 9, /* MPLS TC. */ + OFPFMF11_TYPE = 1 << 10, /* Match type. */ + OFPFMF11_DL_SRC = 1 << 11, /* Ethernet source address. */ + OFPFMF11_DL_DST = 1 << 12, /* Ethernet destination address. */ + OFPFMF11_NW_SRC = 1 << 13, /* IP source address. */ + OFPFMF11_NW_DST = 1 << 14, /* IP destination address. */ + OFPFMF11_METADATA = 1 << 15, /* Metadata passed between tables. */ +}; + /* Body of reply to OFPST_TABLE request. */ struct ofp11_table_stats { uint8_t table_id; /* Identifier of table. Lower numbered tables diff --git a/include/openflow/openflow-1.2.h b/include/openflow/openflow-1.2.h index 0a73ed17b..f6befdbec 100644 --- a/include/openflow/openflow-1.2.h +++ b/include/openflow/openflow-1.2.h @@ -106,8 +106,13 @@ enum oxm12_ofb_match_fields { OFPXMT12_OFB_IPV6_ND_TLL, /* Target link-layer for ND. */ OFPXMT12_OFB_MPLS_LABEL, /* MPLS label. */ OFPXMT12_OFB_MPLS_TC, /* MPLS TC. */ + + /* End Marker */ + OFPXMT12_OFB_MAX, }; +#define OFPXMT12_MASK ((1ULL << OFPXMT12_OFB_MAX) - 1) + /* OXM implementation makes use of NXM as they are the same format * with different field definitions */ @@ -216,12 +221,11 @@ enum ofp12_controller_max_len { struct ofp12_action_set_field { ovs_be16 type; /* OFPAT12_SET_FIELD. */ ovs_be16 len; /* Length is padded to 64 bits. */ + ovs_be32 dst; /* OXM TLV header */ /* Followed by: - * - Exactly oxm_len bytes containing a single OXM TLV, then * - Exactly ((oxm_len + 4) + 7)/8*8 - (oxm_len + 4) (between 0 and 7) * bytes of all-zero bytes */ - uint8_t field[4]; /* OXM TLV - Make compiler happy */ }; OFP_ASSERT(sizeof(struct ofp12_action_set_field) == 8); diff --git a/lib/autopath.c b/lib/autopath.c index ae8007dee..b204e8473 100644 --- a/lib/autopath.c +++ b/lib/autopath.c @@ -36,7 +36,6 @@ void autopath_parse(struct ofpact_autopath *ap, const char *s_) { char *s; - int id_int; char *id_str, *dst, *save_ptr; ofpact_init_AUTOPATH(ap); @@ -50,12 +49,10 @@ autopath_parse(struct ofpact_autopath *ap, const char *s_) ovs_fatal(0, "%s: not enough arguments to autopath action", s_); } - id_int = atoi(id_str); - if (id_int < 1 || id_int > UINT32_MAX) { - ovs_fatal(0, "%s: autopath id %d is not in valid range " - "1 to %"PRIu32, s_, id_int, UINT32_MAX); + ap->port = ofputil_port_from_string(id_str); + if (!ap->port) { + ovs_fatal(0, "%s: bad port number", s_); } - ap->port = id_int; mf_parse_subfield(&ap->dst, dst); if (ap->dst.n_bits < 16) { diff --git a/lib/bundle.c b/lib/bundle.c index e0f8e6b6c..b68ebab83 100644 --- a/lib/bundle.c +++ b/lib/bundle.c @@ -267,12 +267,15 @@ bundle_parse__(const char *s, char **save_ptr, uint16_t slave_port; char *slave; - slave = strtok_r(NULL, ", [", save_ptr); + slave = strtok_r(NULL, ", []", save_ptr); if (!slave || bundle->n_slaves >= BUNDLE_MAX_SLAVES) { break; } - slave_port = atoi(slave); + slave_port = ofputil_port_from_string(slave); + if (!slave_port) { + ovs_fatal(0, "%s: bad port number", slave); + } ofpbuf_put(ofpacts, &slave_port, sizeof slave_port); bundle = ofpacts->l2; @@ -387,7 +390,7 @@ bundle_format(const struct ofpact_bundle *bundle, struct ds *s) ds_put_cstr(s, ","); } - ds_put_format(s, "%"PRIu16, bundle->slaves[i]); + ofputil_format_port(bundle->slaves[i], s); } ds_put_cstr(s, ")"); diff --git a/lib/flow.c b/lib/flow.c index a2172a9c4..e517a0376 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -509,7 +509,8 @@ flow_format(struct ds *ds, const struct flow *flow) ds_put_cstr(ds, "->"); print_ipv6_addr(ds, &flow->ipv6_dst); ds_put_char(ds, ')'); - } else { + } else if (flow->dl_type == htons(ETH_TYPE_IP) || + flow->dl_type == htons(ETH_TYPE_ARP)) { ds_put_format(ds, " proto:%"PRIu8" tos:%#"PRIx8" ttl:%"PRIu8 " ip("IP_FMT"->"IP_FMT")", flow->nw_proto, flow->nw_tos, flow->nw_ttl, diff --git a/lib/meta-flow.c b/lib/meta-flow.c index aa44ce8d5..38c9a27aa 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -1941,7 +1941,8 @@ mf_from_ofp_port_string(const struct mf_field *mf, const char *s, uint16_t port; assert(mf->n_bytes == sizeof(ovs_be16)); - if (ofputil_port_from_string(s, &port)) { + port = ofputil_port_from_string(s); + if (port) { *valuep = htons(port); *maskp = htons(UINT16_MAX); return NULL; diff --git a/lib/nx-match.c b/lib/nx-match.c index 17ef1600e..6ea064256 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -1019,14 +1019,39 @@ nxm_format_reg_move(const struct ofpact_reg_move *move, struct ds *s) mf_format_subfield(&move->dst, s); } -void -nxm_format_reg_load(const struct ofpact_reg_load *load, struct ds *s) +static void +set_field_format(const struct ofpact_reg_load *load, struct ds *s) +{ + const struct mf_field *mf = load->dst.field; + union mf_value value; + + assert(load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD); + ds_put_format(s, "set_field:"); + memset(&value, 0, sizeof value); + bitwise_copy(&load->subvalue, sizeof load->subvalue, 0, + &value, mf->n_bytes, 0, load->dst.n_bits); + mf_format(mf, &value, NULL, s); + ds_put_format(s, "->%s", mf->name); +} + +static void +load_format(const struct ofpact_reg_load *load, struct ds *s) { ds_put_cstr(s, "load:"); mf_format_subvalue(&load->subvalue, s); ds_put_cstr(s, "->"); mf_format_subfield(&load->dst, s); } + +void +nxm_format_reg_load(const struct ofpact_reg_load *load, struct ds *s) +{ + if (load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD) { + set_field_format(load, s); + } else { + load_format(load, s); + } +} enum ofperr nxm_reg_move_from_openflow(const struct nx_action_reg_move *narm, @@ -1066,6 +1091,43 @@ nxm_reg_load_from_openflow(const struct nx_action_reg_load *narl, return nxm_reg_load_check(load, NULL); } + +enum ofperr +nxm_reg_load_from_openflow12_set_field( + const struct ofp12_action_set_field * oasf, struct ofpbuf *ofpacts) +{ + uint16_t oasf_len = ntohs(oasf->len); + uint32_t oxm_header = ntohl(oasf->dst); + uint8_t oxm_length = NXM_LENGTH(oxm_header); + struct ofpact_reg_load *load; + const struct mf_field *mf; + + /* ofp12_action_set_field is padded to 64 bits by zero */ + if (oasf_len != ROUND_UP(sizeof(*oasf) + oxm_length, 8)) { + return OFPERR_OFPBAC_BAD_ARGUMENT; + } + if (!is_all_zeros((const uint8_t *)(oasf) + sizeof *oasf + oxm_length, + oasf_len - oxm_length - sizeof *oasf)) { + return OFPERR_OFPBAC_BAD_ARGUMENT; + } + + if (NXM_HASMASK(oxm_header)) { + return OFPERR_OFPBAC_BAD_ARGUMENT; + } + mf = mf_from_nxm_header(oxm_header); + if (!mf) { + return OFPERR_OFPBAC_BAD_ARGUMENT; + } + load = ofpact_put_REG_LOAD(ofpacts); + load->ofpact.compat = OFPUTIL_OFPAT12_SET_FIELD; + load->dst.field = mf; + load->dst.ofs = 0; + load->dst.n_bits = mf->n_bits; + bitwise_copy(oasf + 1, mf->n_bytes, load->dst.ofs, + &load->subvalue, sizeof load->subvalue, 0, mf->n_bits); + + return nxm_reg_load_check(load, NULL); +} enum ofperr nxm_reg_move_check(const struct ofpact_reg_move *move, const struct flow *flow) @@ -1100,9 +1162,8 @@ nxm_reg_move_to_nxast(const struct ofpact_reg_move *move, narm->dst = htonl(move->dst.field->nxm_header); } -void -nxm_reg_load_to_nxast(const struct ofpact_reg_load *load, - struct ofpbuf *openflow) +static void +reg_load_to_nxast(const struct ofpact_reg_load *load, struct ofpbuf *openflow) { struct nx_action_reg_load *narl; @@ -1111,6 +1172,73 @@ nxm_reg_load_to_nxast(const struct ofpact_reg_load *load, narl->dst = htonl(load->dst.field->nxm_header); narl->value = load->subvalue.be64[1]; } + +static void +set_field_to_ofast(const struct ofpact_reg_load *load, + struct ofpbuf *openflow) +{ + const struct mf_field *mf = load->dst.field; + struct ofp12_action_set_field *oasf; + uint16_t padded_value_len; + + oasf = ofputil_put_OFPAT12_SET_FIELD(openflow); + oasf->dst = htonl(mf->oxm_header); + + /* Set field is the only action of variable length (so far), + * so handling the variable length portion is open-coded here */ + padded_value_len = ROUND_UP(mf->n_bytes, 8); + ofpbuf_put_uninit(openflow, padded_value_len); + oasf->len = htons(ntohs(oasf->len) + padded_value_len); + memset(oasf + 1, 0, padded_value_len); + + bitwise_copy(&load->subvalue, sizeof load->subvalue, load->dst.ofs, + oasf + 1, mf->n_bytes, load->dst.ofs, load->dst.n_bits); + return; +} + +void +nxm_reg_load_to_nxast(const struct ofpact_reg_load *load, + struct ofpbuf *openflow) +{ + + if (load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD) { + struct ofp_header *oh = (struct ofp_header *)openflow->l2; + + switch(oh->version) { + case OFP12_VERSION: + set_field_to_ofast(load, openflow); + break; + + case OFP11_VERSION: + case OFP10_VERSION: + if (load->dst.n_bits < 64) { + reg_load_to_nxast(load, openflow); + } else { + /* Split into 64bit chunks */ + int chunk, ofs; + for (ofs = 0; ofs < load->dst.n_bits; ofs += chunk) { + struct ofpact_reg_load subload = *load; + + chunk = MIN(load->dst.n_bits - ofs, 64); + + subload.dst.field = load->dst.field; + subload.dst.ofs = load->dst.ofs + ofs; + subload.dst.n_bits = chunk; + bitwise_copy(&load->subvalue, sizeof load->subvalue, ofs, + &subload.subvalue, sizeof subload.subvalue, 0, + chunk); + reg_load_to_nxast(&subload, openflow); + } + } + break; + + default: + NOT_REACHED(); + } + } else { + reg_load_to_nxast(load, openflow); + } +} /* nxm_execute_reg_move(), nxm_execute_reg_load(). */ diff --git a/lib/nx-match.h b/lib/nx-match.h index f504ad07d..6a57297cb 100644 --- a/lib/nx-match.h +++ b/lib/nx-match.h @@ -65,6 +65,8 @@ enum ofperr nxm_reg_move_from_openflow(const struct nx_action_reg_move *, struct ofpbuf *ofpacts); enum ofperr nxm_reg_load_from_openflow(const struct nx_action_reg_load *, struct ofpbuf *ofpacts); +enum ofperr nxm_reg_load_from_openflow12_set_field( + const struct ofp12_action_set_field * oasf, struct ofpbuf *ofpacts); enum ofperr nxm_reg_move_check(const struct ofpact_reg_move *, const struct flow *); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 210f4ce6e..19ed7a02e 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -1770,7 +1770,8 @@ ofpact_format(const struct ofpact *a, struct ds *s) case OFPACT_RESUBMIT: resubmit = ofpact_get_RESUBMIT(a); if (resubmit->in_port != OFPP_IN_PORT && resubmit->table_id == 255) { - ds_put_format(s, "resubmit:%"PRIu16, resubmit->in_port); + ds_put_cstr(s, "resubmit:"); + ofputil_format_port(resubmit->in_port, s); } else { ds_put_format(s, "resubmit("); if (resubmit->in_port != OFPP_IN_PORT) { @@ -1794,7 +1795,9 @@ ofpact_format(const struct ofpact *a, struct ds *s) case OFPACT_AUTOPATH: autopath = ofpact_get_AUTOPATH(a); - ds_put_format(s, "autopath(%u,", autopath->port); + ds_put_cstr(s, "autopath("); + ofputil_format_port(autopath->port, s); + ds_put_char(s, ','); mf_format_subfield(&autopath->dst, s); ds_put_char(s, ')'); break; diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h index 75ccc26e4..46e2d79ae 100644 --- a/lib/ofp-actions.h +++ b/lib/ofp-actions.h @@ -108,7 +108,31 @@ enum { * * Each action is a structure "struct ofpact_*" that begins with "struct * ofpact", usually followed by other data that describes the action. Actions - * are padded out to a multiple of OFPACT_ALIGNTO bytes in length. */ + * are padded out to a multiple of OFPACT_ALIGNTO bytes in length. + * + * The 'compat' member is special: + * + * - Most "struct ofpact"s correspond to one particular kind of OpenFlow + * action, at least in a given OpenFlow version. For example, + * OFPACT_SET_VLAN_VID corresponds to OFPAT10_SET_VLAN_VID in OpenFlow + * 1.0. + * + * For such actions, the 'compat' member is not meaningful and generally + * should be zero. + * + * - A few "struct ofpact"s correspond to multiple OpenFlow actions. For + * example, OFPACT_SET_TUNNEL can be NXAST_SET_TUNNEL or + * NXAST_SET_TUNNEL64. In these cases, if the "struct ofpact" originated + * from OpenFlow, then we want to make sure that, if it gets translated + * back to OpenFlow later, it is translated back to the same action type. + * (Otherwise, we'd violate the promise made in DESIGN, in the "Action + * Reproduction" section.) + * + * For such actions, the 'compat' member should be the original action + * type. (If the action didn't originate from OpenFlow, then setting + * 'compat' to zero should be fine: code to translate the ofpact to + * OpenFlow must tolerate this case.) + */ struct ofpact { enum ofpact_type type; /* OFPACT_*. */ enum ofputil_action_code compat; /* Original type when added, if any. */ diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 165a36e81..e3b7dc122 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -168,8 +168,9 @@ parse_resubmit(char *arg, struct ofpbuf *ofpacts) in_port_s = strsep(&arg, ","); if (in_port_s && in_port_s[0]) { - if (!ofputil_port_from_string(in_port_s, &resubmit->in_port)) { - resubmit->in_port = str_to_u32(in_port_s); + resubmit->in_port = ofputil_port_from_string(in_port_s); + if (!resubmit->in_port) { + ovs_fatal(0, "%s: resubmit to unknown port", in_port_s); } } else { resubmit->in_port = OFPP_IN_PORT; @@ -488,10 +489,7 @@ str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts) pos = str; n_actions = 0; while (ofputil_parse_key_value(&pos, &act, &arg)) { - uint16_t port; - int code; - - code = ofputil_action_code_from_name(act); + int code = ofputil_action_code_from_name(act); if (code >= 0) { parse_named_action(code, flow, arg, ofpacts); } else if (!strcasecmp(act, "drop")) { @@ -503,10 +501,13 @@ str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts) "actions"); } break; - } else if (ofputil_port_from_string(act, &port)) { - ofpact_put_OUTPUT(ofpacts)->port = port; } else { - ovs_fatal(0, "Unknown action: %s", act); + uint16_t port = ofputil_port_from_string(act); + if (port) { + ofpact_put_OUTPUT(ofpacts)->port = port; + } else { + ovs_fatal(0, "Unknown action: %s", act); + } } n_actions++; } @@ -681,7 +682,11 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, if (!strcmp(name, "table")) { fm->table_id = str_to_table_id(value); } else if (!strcmp(name, "out_port")) { - fm->out_port = atoi(value); + fm->out_port = ofputil_port_from_string(name); + if (!fm->out_port) { + ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port", + name); + } } else if (fields & F_PRIORITY && !strcmp(name, "priority")) { fm->priority = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) { diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 1976b9430..fc988946d 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -2933,6 +2933,143 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, return b; } +/* Table stats. */ + +static void +ofputil_put_ofp10_table_stats(const struct ofp12_table_stats *in, + struct ofpbuf *buf) +{ + struct wc_map { + enum ofp_flow_wildcards wc10; + enum oxm12_ofb_match_fields mf12; + }; + + static const struct wc_map wc_map[] = { + { OFPFW10_IN_PORT, OFPXMT12_OFB_IN_PORT }, + { OFPFW10_DL_VLAN, OFPXMT12_OFB_VLAN_VID }, + { OFPFW10_DL_SRC, OFPXMT12_OFB_ETH_SRC }, + { OFPFW10_DL_DST, OFPXMT12_OFB_ETH_DST}, + { OFPFW10_DL_TYPE, OFPXMT12_OFB_ETH_TYPE }, + { OFPFW10_NW_PROTO, OFPXMT12_OFB_IP_PROTO }, + { OFPFW10_TP_SRC, OFPXMT12_OFB_TCP_SRC }, + { OFPFW10_TP_DST, OFPXMT12_OFB_TCP_DST }, + { OFPFW10_NW_SRC_MASK, OFPXMT12_OFB_IPV4_SRC }, + { OFPFW10_NW_DST_MASK, OFPXMT12_OFB_IPV4_DST }, + { OFPFW10_DL_VLAN_PCP, OFPXMT12_OFB_VLAN_PCP }, + { OFPFW10_NW_TOS, OFPXMT12_OFB_IP_DSCP }, + }; + + struct ofp10_table_stats *out; + const struct wc_map *p; + + out = ofpbuf_put_uninit(buf, sizeof *out); + out->table_id = in->table_id; + strcpy(out->name, in->name); + out->wildcards = 0; + for (p = wc_map; p < &wc_map[ARRAY_SIZE(wc_map)]; p++) { + if (in->wildcards & htonll(1ULL << p->mf12)) { + out->wildcards |= htonl(p->wc10); + } + } + out->max_entries = in->max_entries; + out->active_count = in->active_count; + put_32aligned_be64(&out->lookup_count, in->lookup_count); + put_32aligned_be64(&out->matched_count, in->matched_count); +} + +static ovs_be32 +oxm12_to_ofp11_flow_match_fields(ovs_be64 oxm12) +{ + struct map { + enum ofp11_flow_match_fields fmf11; + enum oxm12_ofb_match_fields mf12; + }; + + static const struct map map[] = { + { OFPFMF11_IN_PORT, OFPXMT12_OFB_IN_PORT }, + { OFPFMF11_DL_VLAN, OFPXMT12_OFB_VLAN_VID }, + { OFPFMF11_DL_VLAN_PCP, OFPXMT12_OFB_VLAN_PCP }, + { OFPFMF11_DL_TYPE, OFPXMT12_OFB_ETH_TYPE }, + { OFPFMF11_NW_TOS, OFPXMT12_OFB_IP_DSCP }, + { OFPFMF11_NW_PROTO, OFPXMT12_OFB_IP_PROTO }, + { OFPFMF11_TP_SRC, OFPXMT12_OFB_TCP_SRC }, + { OFPFMF11_TP_DST, OFPXMT12_OFB_TCP_DST }, + { OFPFMF11_MPLS_LABEL, OFPXMT12_OFB_MPLS_LABEL }, + { OFPFMF11_MPLS_TC, OFPXMT12_OFB_MPLS_TC }, + /* I don't know what OFPFMF11_TYPE means. */ + { OFPFMF11_DL_SRC, OFPXMT12_OFB_ETH_SRC }, + { OFPFMF11_DL_DST, OFPXMT12_OFB_ETH_DST }, + { OFPFMF11_NW_SRC, OFPXMT12_OFB_IPV4_SRC }, + { OFPFMF11_NW_DST, OFPXMT12_OFB_IPV4_DST }, + { OFPFMF11_METADATA, OFPXMT12_OFB_METADATA }, + }; + + const struct map *p; + uint32_t fmf11; + + fmf11 = 0; + for (p = map; p < &map[ARRAY_SIZE(map)]; p++) { + if (oxm12 & htonll(1ULL << p->mf12)) { + fmf11 |= p->fmf11; + } + } + return htonl(fmf11); +} + +static void +ofputil_put_ofp11_table_stats(const struct ofp12_table_stats *in, + struct ofpbuf *buf) +{ + struct ofp11_table_stats *out; + + out = ofpbuf_put_uninit(buf, sizeof *out); + out->table_id = in->table_id; + strcpy(out->name, in->name); + out->wildcards = oxm12_to_ofp11_flow_match_fields(in->wildcards); + out->match = oxm12_to_ofp11_flow_match_fields(in->match); + out->instructions = in->instructions; + out->write_actions = in->write_actions; + out->apply_actions = in->apply_actions; + out->config = in->config; + out->max_entries = in->max_entries; + out->active_count = in->active_count; + out->lookup_count = in->lookup_count; + out->matched_count = in->matched_count; +} + +struct ofpbuf * +ofputil_encode_table_stats_reply(const struct ofp12_table_stats stats[], int n, + const struct ofp_header *request) +{ + struct ofpbuf *reply; + int i; + + reply = ofpraw_alloc_stats_reply(request, n * sizeof *stats); + + switch ((enum ofp_version) request->version) { + case OFP10_VERSION: + for (i = 0; i < n; i++) { + ofputil_put_ofp10_table_stats(&stats[i], reply); + } + break; + + case OFP11_VERSION: + for (i = 0; i < n; i++) { + ofputil_put_ofp11_table_stats(&stats[i], reply); + } + break; + + case OFP12_VERSION: + ofpbuf_put(reply, stats, n * sizeof *stats); + break; + + default: + NOT_REACHED(); + } + + return reply; +} + /* ofputil_flow_monitor_request */ /* Converts an NXST_FLOW_MONITOR request in 'msg' into an abstract @@ -3399,36 +3536,72 @@ ofputil_check_output_port(uint16_t port, int max_ports) OFPUTIL_NAMED_PORT(LOCAL) \ OFPUTIL_NAMED_PORT(NONE) -/* Checks whether 's' is the string representation of an OpenFlow port number, - * either as an integer or a string name (e.g. "LOCAL"). If it is, stores the - * number in '*port' and returns true. Otherwise, returns false. */ -bool -ofputil_port_from_string(const char *name, uint16_t *port) +/* Returns the port number represented by 's', which may be an integer or, for + * reserved ports, the standard OpenFlow name for the port (e.g. "LOCAL"). + * + * Returns 0 if 's' is not a valid OpenFlow port number or name. The caller + * should issue an error message in this case, because this function usually + * does not. (This gives the caller an opportunity to look up the port name + * another way, e.g. by contacting the switch and listing the names of all its + * ports). + * + * This function accepts OpenFlow 1.0 port numbers. It also accepts a subset + * of OpenFlow 1.1+ port numbers, mapping those port numbers into the 16-bit + * range as described in include/openflow/openflow-1.1.h. */ +uint16_t +ofputil_port_from_string(const char *s) { - struct pair { - const char *name; - uint16_t value; - }; - static const struct pair pairs[] = { + unsigned int port32; + + if (str_to_uint(s, 10, &port32)) { + if (port32 == 0) { + VLOG_WARN("port 0 is not a valid OpenFlow port number"); + return 0; + } else if (port32 < OFPP_MAX) { + return port32; + } else if (port32 < OFPP_FIRST_RESV) { + VLOG_WARN("port %u is a reserved OF1.0 port number that will " + "be translated to %u when talking to an OF1.1 or " + "later controller", port32, port32 + OFPP11_OFFSET); + return port32; + } else if (port32 <= OFPP_LAST_RESV) { + struct ds s; + + ds_init(&s); + ofputil_format_port(port32, &s); + VLOG_WARN("port %u is better referred to as %s, for compatibility " + "with future versions of OpenFlow", + port32, ds_cstr(&s)); + ds_destroy(&s); + + return port32; + } else if (port32 < OFPP11_MAX) { + VLOG_WARN("port %u is outside the supported range 0 through " + "%"PRIx16"or 0x%x through 0x%"PRIx32, port32, + UINT16_MAX, (unsigned int) OFPP11_MAX, UINT32_MAX); + return 0; + } else { + return port32 - OFPP11_OFFSET; + } + } else { + struct pair { + const char *name; + uint16_t value; + }; + static const struct pair pairs[] = { #define OFPUTIL_NAMED_PORT(NAME) {#NAME, OFPP_##NAME}, - OFPUTIL_NAMED_PORTS + OFPUTIL_NAMED_PORTS #undef OFPUTIL_NAMED_PORT - }; - static const int n_pairs = ARRAY_SIZE(pairs); - int i; - - if (str_to_int(name, 0, &i) && i >= 0 && i < UINT16_MAX) { - *port = i; - return true; - } + }; + const struct pair *p; - for (i = 0; i < n_pairs; i++) { - if (!strcasecmp(name, pairs[i].name)) { - *port = pairs[i].value; - return true; + for (p = pairs; p < &pairs[ARRAY_SIZE(pairs)]; p++) { + if (!strcasecmp(s, p->name)) { + return p->value; + } } + return 0; } - return false; } /* Appends to 's' a string representation of the OpenFlow port number 'port'. diff --git a/lib/ofp-util.h b/lib/ofp-util.h index e3a93c977..4e9f946f0 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -36,7 +36,7 @@ enum ofperr ofputil_port_from_ofp11(ovs_be32 ofp11_port, uint16_t *ofp10_port); ovs_be32 ofputil_port_to_ofp11(uint16_t ofp10_port); enum ofperr ofputil_check_output_port(uint16_t ofp_port, int max_ports); -bool ofputil_port_from_string(const char *, uint16_t *port); +uint16_t ofputil_port_from_string(const char *); void ofputil_format_port(uint16_t port, struct ds *); /* Converting OFPFW10_NW_SRC_MASK and OFPFW10_NW_DST_MASK wildcard bit counts @@ -450,6 +450,15 @@ enum ofperr ofputil_decode_port_mod(const struct ofp_header *, struct ofpbuf *ofputil_encode_port_mod(const struct ofputil_port_mod *, enum ofputil_protocol); +/* Abstract table stats. + * + * For now we use ofp12_table_stats as a superset of the other protocol + * versions' table stats. */ + +struct ofpbuf *ofputil_encode_table_stats_reply( + const struct ofp12_table_stats[], int n, + const struct ofp_header *request); + /* Abstract nx_flow_monitor_request. */ struct ofputil_flow_monitor_request { uint32_t id; diff --git a/lib/stream-unix.c b/lib/stream-unix.c index 689dcf1cf..dde599683 100644 --- a/lib/stream-unix.c +++ b/lib/stream-unix.c @@ -48,7 +48,7 @@ unix_open(const char *name, char *suffix, struct stream **streamp, fd = make_unix_socket(SOCK_STREAM, true, NULL, connect_path); if (fd < 0) { - VLOG_ERR("%s: connection failed (%s)", connect_path, strerror(-fd)); + VLOG_WARN("%s: connection failed (%s)", connect_path, strerror(-fd)); return -fd; } diff --git a/lib/unixctl.c b/lib/unixctl.c index 4ab493d48..8686de3fb 100644 --- a/lib/unixctl.c +++ b/lib/unixctl.c @@ -95,13 +95,13 @@ unixctl_version(struct unixctl_conn *conn, int argc OVS_UNUSED, * arguments to the command; it is used only for presentation to the user in * "help" output. * - * 'cb' is called when the command is received. It is passed the actual set of - * arguments, as a text string, plus a copy of 'aux'. Normally 'cb' should - * reply by calling unixctl_command_reply() or unixctl_command_reply_error() - * before it returns, but if the command cannot be handled immediately then it - * can defer the reply until later. A given connection can only process a - * single request at a time, so a reply must be made eventually to avoid - * blocking that connection. */ + * 'cb' is called when the command is received. It is passed an array + * containing the command name and arguments, plus a copy of 'aux'. Normally + * 'cb' should reply by calling unixctl_command_reply() or + * unixctl_command_reply_error() before it returns, but if the command cannot + * be handled immediately then it can defer the reply until later. A given + * connection can only process a single request at a time, so a reply must be + * made eventually to avoid blocking that connection. */ void unixctl_command_register(const char *name, const char *usage, int min_args, int max_args, diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c index 391995e7a..05e69c7f9 100644 --- a/ofproto/connmgr.c +++ b/ofproto/connmgr.c @@ -1815,6 +1815,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule, fu.cookie = rule->flow_cookie; minimatch_expand(&rule->cr.match, &match); fu.match = &match; + fu.priority = rule->cr.priority; if (flags & NXFMF_ACTIONS) { fu.ofpacts = rule->ofpacts; fu.ofpacts_len = rule->ofpacts_len; diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 1289025ba..9f7acd1d3 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1158,7 +1158,7 @@ get_features(struct ofproto *ofproto_ OVS_UNUSED, } static void -get_tables(struct ofproto *ofproto_, struct ofp10_table_stats *ots) +get_tables(struct ofproto *ofproto_, struct ofp12_table_stats *ots) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); struct dpif_dp_stats s; @@ -1166,9 +1166,8 @@ get_tables(struct ofproto *ofproto_, struct ofp10_table_stats *ots) 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)); + ots->lookup_count = htonll(s.n_hit + s.n_missed); + ots->matched_count = htonll(s.n_hit + ofproto->n_matches); } static struct ofport * diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index fb7db2304..0ade586c7 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -464,7 +464,17 @@ struct ofproto_class { * * - 'name' to "table#" where # is the table ID. * - * - 'wildcards' to OFPFW10_ALL. + * - 'match' and 'wildcards' to OFPXMT12_MASK. + * + * - 'write_actions' and 'apply_actions' to OFPAT12_OUTPUT. + * + * - 'write_setfields' and 'apply_setfields' to OFPXMT12_MASK. + * + * - 'metadata_match' and 'metadata_write' to UINT64_MAX. + * + * - 'instructions' to OFPIT11_ALL. + * + * - 'config' to OFPTC11_TABLE_MISS_MASK. * * - 'max_entries' to 1,000,000. * @@ -480,6 +490,21 @@ struct ofproto_class { * - 'wildcards' to the set of wildcards actually supported by the table * (if it doesn't support all OpenFlow wildcards). * + * - 'instructions' to set the instructions actually supported by + * the table. + * + * - 'write_actions' to set the write actions actually supported by + * the table (if it doesn't support all OpenFlow actions). + * + * - 'apply_actions' to set the apply actions actually supported by + * the table (if it doesn't support all OpenFlow actions). + * + * - 'write_setfields' to set the write setfields actually supported by + * the table. + * + * - 'apply_setfields' to set the apply setfields actually supported by + * the table. + * * - 'max_entries' to the maximum number of flows actually supported by * the hardware. * @@ -489,10 +514,10 @@ struct ofproto_class { * - 'matched_count' to the number of packets looked up in this flow * table so far that matched one of the flow entries. * - * Keep in mind that all of the members of struct ofp10_table_stats are in - * network byte order. + * All of the members of struct ofp12_table_stats are in network byte + * order. */ - void (*get_tables)(struct ofproto *ofproto, struct ofp10_table_stats *ots); + void (*get_tables)(struct ofproto *ofproto, struct ofp12_table_stats *ots); /* ## ---------------- ## */ /* ## ofport Functions ## */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 9b235e946..e3b24c1a6 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -2242,16 +2242,30 @@ handle_table_stats_request(struct ofconn *ofconn, const struct ofp_header *request) { struct ofproto *p = ofconn_get_ofproto(ofconn); - struct ofp10_table_stats *ots; + struct ofp12_table_stats *ots; struct ofpbuf *msg; size_t i; - msg = ofpraw_alloc_stats_reply(request, sizeof *ots * p->n_tables); - ots = ofpbuf_put_zeros(msg, sizeof *ots * p->n_tables); + /* Set up default values. + * + * ofp12_table_stats is used as a generic structure as + * it is able to hold all the fields for ofp10_table_stats + * and ofp11_table_stats (and of course itself). + */ + ots = xcalloc(p->n_tables, sizeof *ots); for (i = 0; i < p->n_tables; i++) { ots[i].table_id = i; sprintf(ots[i].name, "table%zu", i); - ots[i].wildcards = htonl(OFPFW10_ALL); + ots[i].match = htonll(OFPXMT12_MASK); + ots[i].wildcards = htonll(OFPXMT12_MASK); + ots[i].write_actions = htonl(OFPAT12_OUTPUT); + ots[i].apply_actions = htonl(OFPAT12_OUTPUT); + ots[i].write_setfields = htonll(OFPXMT12_MASK); + ots[i].apply_setfields = htonll(OFPXMT12_MASK); + ots[i].metadata_match = htonll(UINT64_MAX); + ots[i].metadata_write = htonll(UINT64_MAX); + ots[i].instructions = htonl(OFPIT11_ALL); + ots[i].config = htonl(OFPTC11_TABLE_MISS_MASK); ots[i].max_entries = htonl(1000000); /* An arbitrary big number. */ ots[i].active_count = htonl(classifier_count(&p->tables[i].cls)); } @@ -2270,7 +2284,11 @@ handle_table_stats_request(struct ofconn *ofconn, } } + msg = ofputil_encode_table_stats_reply(ots, p->n_tables, request); ofconn_send_reply(ofconn, msg); + + free(ots); + return 0; } @@ -3532,6 +3550,7 @@ ofproto_compose_flow_refresh_update(const struct rule *rule, fu.cookie = rule->flow_cookie; minimatch_expand(&rule->cr.match, &match); fu.match = &match; + fu.priority = rule->cr.priority; if (!(flags & NXFMF_ACTIONS)) { fu.ofpacts = NULL; fu.ofpacts_len = 0; diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c index a94d7cbc7..d5d2189ed 100644 --- a/ovsdb/ovsdb-client.c +++ b/ovsdb/ovsdb-client.c @@ -39,7 +39,7 @@ #include "ovsdb-data.h" #include "ovsdb-error.h" #include "sort.h" -#include "sset.h" +#include "svec.h" #include "stream.h" #include "stream-ssl.h" #include "table.h" @@ -75,7 +75,7 @@ static const struct ovsdb_client_command all_commands[]; static void usage(void) NO_RETURN; static void parse_options(int argc, char *argv[]); static struct jsonrpc *open_jsonrpc(const char *server); -static void fetch_dbs(struct jsonrpc *, struct sset *dbs); +static void fetch_dbs(struct jsonrpc *, struct svec *dbs); int main(int argc, char *argv[]) @@ -118,22 +118,22 @@ main(int argc, char *argv[]) } if (command->need == NEED_DATABASE) { - struct sset dbs; + struct svec dbs; - sset_init(&dbs); + svec_init(&dbs); fetch_dbs(rpc, &dbs); if (argc - optind > command->min_args - && sset_contains(&dbs, argv[optind])) { + && svec_contains(&dbs, argv[optind])) { database = argv[optind++]; - } else if (sset_count(&dbs) == 1) { - database = xstrdup(SSET_FIRST(&dbs)); - } else if (sset_contains(&dbs, "Open_vSwitch")) { + } else if (dbs.n == 1) { + database = xstrdup(dbs.names[0]); + } else if (svec_contains(&dbs, "Open_vSwitch")) { database = "Open_vSwitch"; } else { ovs_fatal(0, "no default database for `%s' command, please " "specify a database name", command->name); } - sset_destroy(&dbs); + svec_destroy(&dbs); } else { database = NULL; } @@ -371,7 +371,7 @@ fetch_schema(struct jsonrpc *rpc, const char *database) } static void -fetch_dbs(struct jsonrpc *rpc, struct sset *dbs) +fetch_dbs(struct jsonrpc *rpc, struct svec *dbs) { struct jsonrpc_msg *request, *reply; size_t i; @@ -390,7 +390,7 @@ fetch_dbs(struct jsonrpc *rpc, struct sset *dbs) if (name->type != JSON_STRING) { ovs_fatal(0, "list_dbs response %zu is not string", i); } - sset_add(dbs, name->u.string); + svec_add(dbs, name->u.string); } jsonrpc_msg_destroy(reply); } @@ -400,14 +400,16 @@ do_list_dbs(struct jsonrpc *rpc, const char *database OVS_UNUSED, int argc OVS_UNUSED, char *argv[] OVS_UNUSED) { const char *db_name; - struct sset dbs; + struct svec dbs; + size_t i; - sset_init(&dbs); + svec_init(&dbs); fetch_dbs(rpc, &dbs); - SSET_FOR_EACH (db_name, &dbs) { + svec_sort(&dbs); + SVEC_FOR_EACH (i, db_name, &dbs) { puts(db_name); } - sset_destroy(&dbs); + svec_destroy(&dbs); } static void diff --git a/ovsdb/ovsdb-tool.1.in b/ovsdb/ovsdb-tool.1.in index 9d3284457..f9a36610b 100644 --- a/ovsdb/ovsdb-tool.1.in +++ b/ovsdb/ovsdb-tool.1.in @@ -134,7 +134,7 @@ instead, to write to a database that is served by Prints a summary of the records in \fIdb\fR's log, including the time and date at which each database change occurred and any associated comment. This may be useful for debugging. -.PP +.IP To increase the verbosity of output, add \fB\-m\fR (or \fB\-\-more\fR) one or more times to the command line. With one \fB\-m\fR, \fBshow\-log\fR prints a summary of the records added, deleted, or diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py index fa66aabac..c1540eb78 100644 --- a/python/ovs/jsonrpc.py +++ b/python/ovs/jsonrpc.py @@ -449,14 +449,16 @@ class Session(object): self.pstream = None if self.rpc: - received_bytes = self.rpc.get_received_bytes() + backlog = self.rpc.get_backlog() self.rpc.run() - if received_bytes != self.rpc.get_received_bytes(): - # Data was successfully received. + if self.rpc.get_backlog() < backlog: + # Data previously caught in a queue was successfully sent (or + # there's an error, which we'll catch below). # - # Previously we only counted receiving a full message as - # activity, but with large messages or a slow connection that - # policy could time out the session mid-message. + # We don't count data that is successfully sent immediately as + # activity, because there's a lot of queuing downstream from + # us, which means that we can push a lot of data into a + # connection that has stalled and won't ever recover. self.reconnect.activity(ovs.timeval.msec()) error = self.rpc.get_status() @@ -516,16 +518,14 @@ class Session(object): def recv(self): if self.rpc is not None: - backlog = self.rpc.get_backlog() + received_bytes = self.rpc.get_received_bytes() error, msg = self.rpc.recv() - if self.rpc.get_backlog() < backlog: - # Data previously caught in a queue was successfully sent (or - # there's an error, which we'll catch below). + if received_bytes != self.rpc.get_received_bytes(): + # Data was successfully received. # - # We don't count data that is successfully sent immediately as - # activity, because there's a lot of queuing downstream from - # us, which means that we can push a lot of data into a - # connection that has stalled and won't ever recover. + # Previously we only counted receiving a full message as + # activity, but with large messages or a slow connection that + # policy could time out the session mid-message. self.reconnect.activity(ovs.timeval.msec()) if not error: diff --git a/tests/autopath.at b/tests/autopath.at index 634d46fc6..557c92c17 100644 --- a/tests/autopath.at +++ b/tests/autopath.at @@ -24,7 +24,7 @@ AT_CLEANUP AT_SETUP([autopath action bad port]) AT_CHECK([ovs-ofctl parse-flow 'actions=autopath(bad, NXM_NX_REG0[[]])'], [1], [], - [ovs-ofctl: bad, NXM_NX_REG0[[]]: autopath id 0 is not in valid range 1 to 4294967295 + [ovs-ofctl: bad, NXM_NX_REG0[[]]: bad port number ]) AT_CLEANUP diff --git a/tests/ofp-print.at b/tests/ofp-print.at index 9844592e1..42b355b17 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -351,7 +351,7 @@ AT_CHECK([ovs-ofctl ofp-print "\ 00 00 00 23 20 83 c1 5f 00 00 00 00 \ "], [0], [dnl OFPT_PACKET_IN (OF1.2) (xid=0x0): total_len=42 in_port=LOCAL (via no_match) data_len=42 buffer=0xffffff00 -priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:23:20:83:c1:5f->ff:ff:ff:ff:ff:ff) type:8035 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0) +priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:23:20:83:c1:5f->ff:ff:ff:ff:ff:ff) type:8035 ]) AT_CLEANUP @@ -794,13 +794,27 @@ OFPST_AGGREGATE reply (OF1.2) (xid=0x2): packet_count=121 byte_count=19279 flow_ ]) AT_CLEANUP -AT_SETUP([OFPST_TABLE request]) +AT_SETUP([OFPST_TABLE request - OF1.0]) AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST]) AT_CHECK([ovs-ofctl ofp-print "0110000c0000000100030000"], [0], [dnl OFPST_TABLE request (xid=0x1): ]) AT_CLEANUP +AT_SETUP([OFPST_TABLE request - OF1.1]) +AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST]) +AT_CHECK([ovs-ofctl ofp-print "02120010000000020003000000000000"], [0], [dnl +OFPST_TABLE request (OF1.1) (xid=0x2): +]) +AT_CLEANUP + +AT_SETUP([OFPST_TABLE request - OF1.2]) +AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST]) +AT_CHECK([ovs-ofctl ofp-print "03120010000000020003000000000000"], [0], [dnl +OFPST_TABLE request (OF1.2) (xid=0x2): +]) +AT_CLEANUP + AT_SETUP([OFPST_TABLE reply - OF1.0]) AT_KEYWORDS([ofp-print OFPT_STATS_REPLY]) AT_CHECK([ovs-ofctl ofp-print "\ diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index cc5d770b6..de56ef8fb 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -968,13 +968,13 @@ AT_CHECK([[sed -e 's/, uptime [0-9]*// s/, now [0-9.]*// s/time \([0-9]*\)\.\.\.\1$/time / s/time [0-9]*\.\.\.[0-9]*/time / -' netflow.log]], [0], - [header: v5, seq 0, engine 2,1 -rec: 192.168.0.1 > 192.168.0.2, if 1 > 65535, 1 pkts, 60 bytes, ICMP 8:0, time - +' netflow.log | sort]], [0], + [ +header: v5, seq 0, engine 2,1 header: v5, seq 1, engine 2,1 -rec: 192.168.0.2 > 192.168.0.1, if 2 > 1, 2 pkts, 120 bytes, ICMP 0:0, time -rec: 192.168.0.1 > 192.168.0.2, if 1 > 2, 1 pkts, 60 bytes, ICMP 8:0, time +seq 0: 192.168.0.1 > 192.168.0.2, if 1 > 65535, 1 pkts, 60 bytes, ICMP 8:0, time +seq 1: 192.168.0.1 > 192.168.0.2, if 1 > 2, 1 pkts, 60 bytes, ICMP 8:0, time +seq 1: 192.168.0.2 > 192.168.0.1, if 2 > 1, 2 pkts, 120 bytes, ICMP 0:0, time ]) AT_CLEANUP @@ -1032,13 +1032,13 @@ while read line; do esac case $line in - "rec: 192.168.0.1 > 192.168.0.2, if 1 > 65535, "*" pkts, "*" bytes, TCP 1234 > 80, time "*) + "seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 65535, "*" pkts, "*" bytes, TCP 1234 > 80, time "*) counter=n_learn ;; - "rec: 192.168.0.1 > 192.168.0.2, if 1 > 2, "*" pkts, "*" bytes, TCP 1234 > 80, time "*) + "seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 2, "*" pkts, "*" bytes, TCP 1234 > 80, time "*) counter=n_in ;; - "rec: 192.168.0.2 > 192.168.0.1, if 2 > 1, "*" pkts, "*" bytes, TCP 80 > 1234, time "*) + "seq "*": 192.168.0.2 > 192.168.0.1, if 2 > 1, "*" pkts, "*" bytes, TCP 80 > 1234, time "*) counter=n_out ;; *) diff --git a/tests/ofproto.at b/tests/ofproto.at index a05585105..af7b7ca5b 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -108,13 +108,13 @@ AT_SETUP([ofproto - basic flow_mod commands (NXM)]) OVS_VSWITCHD_START AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], [0], [NXST_FLOW reply: ]) -AT_CHECK([echo 'in_port=1,actions=0' | ovs-ofctl add-flows br0 -]) -AT_CHECK([ovs-ofctl add-flow br0 in_port=0,actions=1]) -AT_CHECK([ovs-ofctl -F nxm add-flow br0 table=1,in_port=3,actions=2]) +AT_CHECK([echo 'in_port=2,actions=1' | ovs-ofctl add-flows br0 -]) +AT_CHECK([ovs-ofctl add-flow br0 in_port=1,actions=2]) +AT_CHECK([ovs-ofctl -F nxm add-flow br0 table=1,in_port=4,actions=3]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - in_port=0 actions=output:1 - in_port=1 actions=output:0 - table=1, in_port=3 actions=output:2 + in_port=1 actions=output:2 + in_port=2 actions=output:1 + table=1, in_port=4 actions=output:3 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl dump-aggregate br0 table=0 | STRIP_XIDS], [0], [dnl @@ -130,13 +130,13 @@ AT_SETUP([ofproto - basic flow_mod commands (OpenFlow 1.0)]) OVS_VSWITCHD_START AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip], [0], [OFPST_FLOW reply: ]) -AT_CHECK([echo 'in_port=1,actions=0' | ovs-ofctl -F openflow10 add-flows br0 -]) -AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 in_port=0,actions=1]) -AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 table=1,in_port=3,actions=2]) +AT_CHECK([echo 'in_port=2,actions=1' | ovs-ofctl -F openflow10 add-flows br0 -]) +AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 in_port=1,actions=2]) +AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 table=1,in_port=4,actions=3]) AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip | sort], [0], [dnl - in_port=0 actions=output:1 - in_port=1 actions=output:0 - table=1, in_port=3 actions=output:2 + in_port=1 actions=output:2 + in_port=2 actions=output:1 + table=1, in_port=4 actions=output:3 OFPST_FLOW reply: ]) AT_CHECK([ovs-ofctl -F openflow10 dump-aggregate br0 table=0 | STRIP_XIDS], [0], [dnl @@ -150,20 +150,20 @@ AT_CLEANUP AT_SETUP([ofproto - dump flows with cookie]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=0]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x2, in_port=2 actions=output:0 - cookie=0x3, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x2, in_port=2 actions=output:1 + cookie=0x3, in_port=3 actions=output:1 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl dump-aggregate br0 table=0 | STRIP_XIDS], [0], [dnl NXST_AGGREGATE reply: packet_count=0 byte_count=0 flow_count=3 ]) AT_CHECK([ovs-ofctl dump-flows br0 cookie=0x3/-1 | ofctl_strip | sort], [0], [dnl - cookie=0x3, in_port=3 actions=output:0 + cookie=0x3, in_port=3 actions=output:1 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl dump-aggregate br0 cookie=0x3/-1 | STRIP_XIDS], [0], [dnl @@ -174,21 +174,21 @@ AT_CLEANUP AT_SETUP([ofproto - dump flows with cookie mask]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=0]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x2, in_port=2 actions=output:0 - cookie=0x3, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x2, in_port=2 actions=output:1 + cookie=0x3, in_port=3 actions=output:1 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl dump-aggregate br0 table=0 | STRIP_XIDS], [0], [dnl NXST_AGGREGATE reply: packet_count=0 byte_count=0 flow_count=3 ]) AT_CHECK([ovs-ofctl dump-flows br0 cookie=0x3/0x1 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x3, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x3, in_port=3 actions=output:1 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl dump-aggregate br0 cookie=0x3/0x1 | STRIP_XIDS], [0], [dnl @@ -199,15 +199,15 @@ AT_CLEANUP AT_SETUP([ofproto - mod flow with cookie change (OpenFlow 1.0)]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 cookie=0x1,in_port=1,actions=0]) +AT_CHECK([ovs-ofctl -F openflow10 add-flow br0 cookie=0x1,in_port=1,actions=1]) AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 OFPST_FLOW reply: ]) -AT_CHECK([ovs-ofctl -F openflow10 mod-flows br0 cookie=0x2,in_port=1,actions=0]) +AT_CHECK([ovs-ofctl -F openflow10 mod-flows br0 cookie=0x2,in_port=1,actions=1]) AT_CHECK([ovs-ofctl -F openflow10 dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x2, in_port=1 actions=output:0 + cookie=0x2, in_port=1 actions=output:1 OFPST_FLOW reply: ]) OVS_VSWITCHD_STOP @@ -215,15 +215,15 @@ AT_CLEANUP AT_SETUP([ofproto - mod flow with cookie change (NXM)]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl -F nxm add-flow br0 cookie=0x1,in_port=1,actions=0]) +AT_CHECK([ovs-ofctl -F nxm add-flow br0 cookie=0x1,in_port=1,actions=1]) AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 NXST_FLOW reply: ]) -AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=0x2,in_port=1,actions=0]) +AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=0x2,in_port=1,actions=1]) AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x2, in_port=1 actions=output:0 + cookie=0x2, in_port=1 actions=output:1 NXST_FLOW reply: ]) OVS_VSWITCHD_STOP @@ -231,13 +231,13 @@ AT_CLEANUP AT_SETUP([ofproto - mod flows based on cookie mask]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=2,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=3,actions=0]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=2,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=3,actions=1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x1, in_port=2 actions=output:0 - cookie=0x2, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x1, in_port=2 actions=output:1 + cookie=0x2, in_port=3 actions=output:1 NXST_FLOW reply: ]) @@ -245,7 +245,7 @@ AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=0x1/0xff,actions=4]) AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl cookie=0x1, in_port=1 actions=output:4 cookie=0x1, in_port=2 actions=output:4 - cookie=0x2, in_port=3 actions=output:0 + cookie=0x2, in_port=3 actions=output:1 NXST_FLOW reply: ]) OVS_VSWITCHD_STOP @@ -253,19 +253,19 @@ AT_CLEANUP AT_SETUP([ofproto - mod flows based on cookie mask with cookie change]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=2,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=3,actions=0]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=2,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=3,actions=1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x1, in_port=2 actions=output:0 - cookie=0x2, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x1, in_port=2 actions=output:1 + cookie=0x2, in_port=3 actions=output:1 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=1/-1,cookie=4,actions=4]) AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x2, in_port=3 actions=output:0 + cookie=0x2, in_port=3 actions=output:1 cookie=0x4, in_port=1 actions=output:4 cookie=0x4, in_port=2 actions=output:4 NXST_FLOW reply: @@ -275,9 +275,9 @@ AT_CLEANUP AT_SETUP([ofproto - mod flow with cookie miss (mask==0)]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl -F nxm mod-flows br0 in_port=1,actions=0]) +AT_CHECK([ovs-ofctl -F nxm mod-flows br0 in_port=1,actions=1]) AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl - in_port=1 actions=output:0 + in_port=1 actions=output:1 NXST_FLOW reply: ]) OVS_VSWITCHD_STOP @@ -285,7 +285,7 @@ AT_CLEANUP AT_SETUP([ofproto - mod flow with cookie miss (mask!=0)]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=1/1,in_port=1,actions=0]) +AT_CHECK([ovs-ofctl -F nxm mod-flows br0 cookie=1/1,in_port=1,actions=1]) AT_CHECK([ovs-ofctl -F nxm dump-flows br0 | ofctl_strip | sort], [0], [dnl NXST_FLOW reply: ]) @@ -294,13 +294,13 @@ AT_CLEANUP AT_SETUP([ofproto - del flows with cookies]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=0]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x2, in_port=2 actions=output:0 - cookie=0x3, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x2, in_port=2 actions=output:1 + cookie=0x3, in_port=3 actions=output:1 NXST_FLOW reply: ]) @@ -313,20 +313,20 @@ AT_CLEANUP AT_SETUP([ofproto - del flows based on cookie]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=0]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x2, in_port=2 actions=output:0 - cookie=0x3, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x2, in_port=2 actions=output:1 + cookie=0x3, in_port=3 actions=output:1 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl del-flows br0 cookie=0x3/-1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x2, in_port=2 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x2, in_port=2 actions=output:1 NXST_FLOW reply: ]) OVS_VSWITCHD_STOP @@ -334,18 +334,18 @@ AT_CLEANUP AT_SETUP([ofproto - del flows based on cookie mask]) OVS_VSWITCHD_START -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=0]) -AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=0]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x2,in_port=2,actions=1]) +AT_CHECK([ovs-ofctl add-flow br0 cookie=0x3,in_port=3,actions=1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x1, in_port=1 actions=output:0 - cookie=0x2, in_port=2 actions=output:0 - cookie=0x3, in_port=3 actions=output:0 + cookie=0x1, in_port=1 actions=output:1 + cookie=0x2, in_port=2 actions=output:1 + cookie=0x3, in_port=3 actions=output:1 NXST_FLOW reply: ]) AT_CHECK([ovs-ofctl del-flows br0 cookie=0x3/0x1]) AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl - cookie=0x2, in_port=2 actions=output:0 + cookie=0x2, in_port=2 actions=output:1 NXST_FLOW reply: ]) OVS_VSWITCHD_STOP @@ -588,14 +588,14 @@ check_async () { ovs-ofctl -v packet-out br0 none controller '0001020304050010203040501234' if test X"$1" = X"OFPR_ACTION"; then shift; echo >>expout "OFPT_PACKET_IN: total_len=14 in_port=NONE (via action) data_len=14 (unbuffered) -priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0)" +priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234" fi # OFPT_PACKET_IN, OFPR_NO_MATCH (controller_id=123) ovs-ofctl -v packet-out br0 none 'controller(reason=no_match,id=123)' '0001020304050010203040501234' if test X"$1" = X"OFPR_NO_MATCH"; then shift; echo >>expout "OFPT_PACKET_IN: total_len=14 in_port=NONE (via no_match) data_len=14 (unbuffered) -priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0)" +priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234" fi # OFPT_PACKET_IN, OFPR_INVALID_TTL (controller_id=0) @@ -692,7 +692,7 @@ AT_CAPTURE_FILE([monitor.log]) # Send some packet-outs with OFPP_NONE and OFPP_CONTROLLER (65533) as in_port. AT_CHECK([ovs-ofctl packet-out br0 none controller '0001020304050010203040501234']) -AT_CHECK([ovs-ofctl packet-out br0 65533 controller '0001020304050010203040505678']) +AT_CHECK([ovs-ofctl packet-out br0 controller controller '0001020304050010203040505678']) # Stop the monitor and check its output. ovs-appctl -t ovs-ofctl ofctl/barrier @@ -700,9 +700,9 @@ ovs-appctl -t ovs-ofctl exit AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl OFPT_PACKET_IN: total_len=14 in_port=NONE (via action) data_len=14 (unbuffered) -priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0) +priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 OFPT_PACKET_IN: total_len=14 in_port=CONTROLLER (via action) data_len=14 (unbuffered) -priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:5678 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0) +priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:5678 OFPT_BARRIER_REPLY: ]) @@ -730,7 +730,7 @@ ovs-appctl -t ovs-ofctl exit AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl NXT_PACKET_IN: total_len=14 in_port=NONE metadata=0xfafafafa5a5a5a5a (via action) data_len=14 (unbuffered) -priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 proto:0 tos:0 ttl:0 ip(0.0.0.0->0.0.0.0) +priority:0,tunnel:0,metadata:0,in_port:0000,tci(0) mac(00:10:20:30:40:50->00:01:02:03:04:05) type:1234 OFPT_BARRIER_REPLY: ]) diff --git a/tests/test-netflow.c b/tests/test-netflow.c index 85ab5e743..c37eeafe6 100644 --- a/tests/test-netflow.c +++ b/tests/test-netflow.c @@ -74,7 +74,7 @@ print_netflow(struct ofpbuf *buf) return; } - printf("rec: "IP_FMT" > "IP_FMT, + printf("seq %"PRIu32": "IP_FMT" > "IP_FMT, ntohl(hdr->flow_seq), IP_ARGS(&rec->src_addr), IP_ARGS(&rec->dst_addr)); printf(", if %"PRIu16" > %"PRIu16, diff --git a/utilities/ovs-lib.in b/utilities/ovs-lib.in index 3c63ddd98..01f4dedd3 100644 --- a/utilities/ovs-lib.in +++ b/utilities/ovs-lib.in @@ -39,6 +39,8 @@ fi VERSION='@VERSION@' +DAEMON_CWD=/ + LC_ALL=C; export LC_ALL ## ------------- ## @@ -159,7 +161,6 @@ start_daemon () { fi } -DAEMON_CWD=/ stop_daemon () { if test -e "$rundir/$1.pid"; then if pid=`cat "$rundir/$1.pid"`; then diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index aad93259b..be71f184a 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -71,12 +71,11 @@ Prints to the console detailed information about network devices associated with \fIswitch\fR (version 1.7 or later). This is a subset of the information provided by the \fBshow\fR command. . -.TP -\fBmod\-port \fIswitch\fR \fInetdev\fR \fIaction\fR -Modify characteristics of an interface monitored by \fIswitch\fR. -\fInetdev\fR can be referred to by its OpenFlow assigned port number or -the device name, e.g. \fBeth0\fR. The \fIaction\fR may be any one of the -following: +.IP "\fBmod\-port \fIswitch\fR \fIport\fR \fIaction\fR" +Modify characteristics of port \fBport\fR in \fIswitch\fR. \fIport\fR +may be an OpenFlow port number or name or the keyword \fBLOCAL\fR (the +preferred way to refer to the OpenFlow local port). The \fIaction\fR +may be any one of the following: . .RS .IQ \fBup\fR @@ -180,12 +179,15 @@ The output format is described in \fBTable Entry Output\fR. . .IP "\fBqueue\-stats \fIswitch \fR[\fIport \fR[\fIqueue\fR]]" Prints to the console statistics for the specified \fIqueue\fR on -\fIport\fR within \fIswitch\fR. Either of \fIport\fR or \fIqueue\fR -or both may be omitted (or equivalently specified as \fBALL\fR). If -both are omitted, statistics are printed for all queues on all ports. -If only \fIqueue\fR is omitted, then statistics are printed for all -queues on \fIport\fR; if only \fIport\fR is omitted, then statistics -are printed for \fIqueue\fR on every port where it exists. +\fIport\fR within \fIswitch\fR. \fIport\fR can be an OpenFlow port +number or name, the keyword \fBLOCAL\fR (the preferred way to refer to +the OpenFlow local port), or the keyword \fBALL\fR. Either of +\fIport\fR or \fIqueue\fR or both may be omitted (or equivalently the +keyword \fBALL\fR). If both are omitted, statistics are printed for +all queues on all ports. If only \fIqueue\fR is omitted, then +statistics are printed for all queues on \fIport\fR; if only +\fIport\fR is omitted, then statistics are printed for \fIqueue\fR on +every port where it exists. . .SS "OpenFlow Switch Flow Table Commands" . @@ -250,10 +252,10 @@ differences were found. Connects to \fIswitch\fR and instructs it to execute the OpenFlow \fIactions\fR on each \fIpacket\fR. For the purpose of executing the actions, the packets are considered to have arrived on \fIin_port\fR, -which may be an OpenFlow assigned port number, an OpenFlow port name -(e.g. \fBeth0\fR), the keyword \fBlocal\fR for the OpenFlow ``local'' -port \fBOFPP_LOCAL\fR, or the keyword \fBnone\fR to indicate that the -packet was generated by the switch itself. +which may be an OpenFlow port number or name (e.g. \fBeth0\fR), the +keyword \fBLOCAL\fR (the preferred way to refer to the OpenFlow +``local'' port), or the keyword \fBNONE\fR to indicate that the packet +was generated by the switch itself. . .SS "OpenFlow Switch Monitoring Commands" . @@ -325,7 +327,9 @@ Do not report actions as part of flow updates. Limits the monitoring to the table with the given \fInumber\fR between 0 and 254. By default, all tables are monitored. .IP "\fBout_port=\fIport\fR" -If set, only flows that output to \fIport\fR are monitored. +If set, only flows that output to \fIport\fR are monitored. The +\fIport\fR may be an OpenFlow port number or keyword +(e.g. \fBLOCAL\fR). .IP "\fIfield\fB=\fIvalue\fR" Monitors only flows that have \fIfield\fR specified as the given \fIvalue\fR. Any syntax valid for matching on \fBdump\-flows\fR may @@ -392,9 +396,10 @@ resulting flow matches all packets. The string \fB*\fR or \fBANY\fR may be specified to explicitly mark any of these fields as a wildcard. (\fB*\fR should be quoted to protect it from shell expansion.) . -.IP \fBin_port=\fIport_no\fR -Matches OpenFlow port \fIport_no\fR. Ports are numbered as -displayed by \fBovs\-ofctl show\fR. +.IP \fBin_port=\fIport\fR +Matches OpenFlow port \fIport\fR, which may be an OpenFlow port number +or keyword (e.g. \fBLOCAL\fR). +\fBovs\-ofctl show\fR. .IP (The \fBresubmit\fR action can search OpenFlow flow tables with arbitrary \fBin_port\fR values, so flows that match port numbers that @@ -799,25 +804,28 @@ require an additional field, which must be the final field specified: .IP \fBactions=\fR[\fItarget\fR][\fB,\fItarget\fR...]\fR Specifies a comma-separated list of actions to take on a packet when the flow entry matches. If no \fItarget\fR is specified, then packets -matching the flow are dropped. The \fItarget\fR may be a decimal port +matching the flow are dropped. The \fItarget\fR may be an OpenFlow port number designating the physical port on which to output the packet, or one of the following keywords: . .RS -.IP \fBoutput\fR:\fIport\fR -.IQ \fBoutput\fR:\fIsrc\fB[\fIstart\fB..\fIend\fB] -Outputs the packet. If \fIport\fR is an OpenFlow port number, outputs directly -to it. Otherwise, outputs to the OpenFlow port number read from \fIsrc\fR -which must be an NXM field as described above. Outputting to an NXM field is -an OpenFlow extension which is not supported by standard OpenFlow switches. -.IP -Example: \fBoutput:NXM_NX_REG0[16..31]\fR outputs to the OpenFlow port number -written in the upper half of register 0. -. -.IP \fBenqueue\fR:\fIport\fB:\fIqueue\fR +.IP \fBoutput:\fIport\fR +Outputs the packet to \fIport\fR, which must be an OpenFlow port +number or keyword (e.g. \fBLOCAL\fR). +. +.IP \fBoutput:\fIsrc\fB[\fIstart\fB..\fIend\fB] +Outputs the packet to the OpenFlow port number read from \fIsrc\fR, +which must be an NXM field as described above. For example, +\fBoutput:NXM_NX_REG0[16..31]\fR outputs to the OpenFlow port number +written in the upper half of register 0. This form of \fBoutput\fR +uses an OpenFlow extension that is not supported by standard OpenFlow +switches. +. +.IP \fBenqueue:\fIport\fB:\fIqueue\fR Enqueues the packet on the specified \fIqueue\fR within port -\fIport\fR. The number of supported queues depends on the switch; -some OpenFlow implementations do not support queuing at all. +\fIport\fR, which must be an OpenFlow port number or keyword +(e.g. \fBLOCAL\fR).. The number of supported queues depends on the +switch; some OpenFlow implementations do not support queuing at all. . .IP \fBnormal\fR Subjects the packet to the device's normal L2/L3 processing. (This @@ -1122,7 +1130,6 @@ For best performance, segregate learned flows into a table (using possibly for a lowest-priority ``catch-all'' flow, that is, a flow with no match criteria. (This is why the default \fBtable\fR is 1, to keep the learned flows separate from the primary flow table 0.) -.RE . .IP "\fBfin_timeout(\fIargument\fR[\fB,\fIargument\fR]\fB)" This action changes the idle timeout or hard timeout, or both, of this @@ -1150,6 +1157,7 @@ This action causes Open vSwitch to immediately halt execution of further actions. Those actions which have already been executed are unaffected. Any further actions, including those which may be in other tables, or different levels of the \fBresubmit\fR call stack, are ignored. +.RE . .PP An opaque identifier called a cookie can be used as a handle to identify @@ -1245,7 +1253,8 @@ and \fBdel\-flows\fR commands support one additional optional field: . .TP \fBout_port=\fIport\fR -If set, a matching flow must include an output action to \fIport\fR. +If set, a matching flow must include an output action to \fIport\fR, +which must an OpenFlow port number or name (e.g. \fBlocal\fR). . .SS "Table Entry Output" . diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 5f61fd688..dea88787e 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -741,9 +741,8 @@ fetch_ofputil_phy_port(const char *vconn_name, const char *port_name, static uint16_t str_to_port_no(const char *vconn_name, const char *port_name) { - unsigned int port_no; - - if (str_to_uint(port_name, 10, &port_no)) { + uint16_t port_no = ofputil_port_from_string(port_name); + if (port_no) { return port_no; } else { struct ofputil_phy_port pp; @@ -1466,9 +1465,7 @@ ofctl_packet_out(int argc, char *argv[]) parse_ofpacts(argv[3], &ofpacts); po.buffer_id = UINT32_MAX; - po.in_port = (!strcasecmp(argv[2], "none") ? OFPP_NONE - : !strcasecmp(argv[2], "local") ? OFPP_LOCAL - : str_to_port_no(argv[1], argv[2])); + po.in_port = str_to_port_no(argv[1], argv[2]); po.ofpacts = ofpacts.data; po.ofpacts_len = ofpacts.size; diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 53bb7b905..940e5e7f5 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -305,6 +305,7 @@ bridge_init(const char *remote) ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault_status); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_mpids); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_health); + ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_opstate); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_lacp_current); ovsdb_idl_omit(idl, &ovsrec_interface_col_external_ids);