void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
/* Initialize most of wc. */
flow_wildcards_init_catchall(wc);
}
static bool
-is_delimiter(char c)
+is_delimiter(unsigned char c)
{
return isspace(c) || c == ',';
}
return true;
}
-static bool
-tun_parms_fully_wildcarded(const struct flow_wildcards *wc)
-{
- return (!wc->masks.tunnel.ip_src &&
- !wc->masks.tunnel.ip_dst &&
- !wc->masks.tunnel.ip_ttl &&
- !wc->masks.tunnel.ip_tos &&
- !wc->masks.tunnel.flags);
-}
-
/* Returns a bit-mask of ofputil_protocols that can be used for sending 'match'
* to a switch (e.g. to add or remove a flow). Only NXM can handle tunnel IDs,
* registers, or fixing the Ethernet multicast bit. Otherwise, it's better to
{
const struct flow_wildcards *wc = &match->wc;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
- /* tunnel params other than tun_id can't be sent in a flow_mod */
- if (!tun_parms_fully_wildcarded(wc)) {
+ /* These tunnel params can't be sent in a flow_mod */
+ if (wc->masks.tunnel.ip_ttl
+ || wc->masks.tunnel.ip_tos || wc->masks.tunnel.flags) {
return OFPUTIL_P_NONE;
}
| OFPUTIL_P_OF13_OXM;
}
- /* NXM and OXM support matching tun_id. */
- if (wc->masks.tunnel.tun_id != htonll(0)) {
+ /* NXM and OXM support matching tun_id, tun_src, and tun_dst. */
+ if (wc->masks.tunnel.tun_id != htonll(0)
+ || wc->masks.tunnel.ip_src != htonl(0)
+ || wc->masks.tunnel.ip_dst != htonl(0)) {
return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
| OFPUTIL_P_OF13_OXM;
}
return error;
}
- error = ofpacts_pull_openflow11_instructions(&b, b.size, ofpacts);
+ error = ofpacts_pull_openflow11_instructions(&b, b.size, ofm->table_id,
+ ofpacts);
if (error) {
return error;
}
}
if (ofpacts_pull_openflow11_instructions(msg, length - sizeof *ofs -
- padded_match_len, ofpacts)) {
+ padded_match_len,
+ ofs->table_id, ofpacts)) {
VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
return EINVAL;
}
fr->priority = ntohs(nfr->priority);
fr->cookie = nfr->cookie;
fr->reason = nfr->reason;
- fr->table_id = 255;
+ fr->table_id = nfr->table_id ? nfr->table_id - 1 : 255;
fr->duration_sec = ntohl(nfr->duration_sec);
fr->duration_nsec = ntohl(nfr->duration_nsec);
fr->idle_timeout = ntohs(nfr->idle_timeout);
nfr->cookie = fr->cookie;
nfr->priority = htons(fr->priority);
nfr->reason = fr->reason;
+ nfr->table_id = fr->table_id + 1;
nfr->duration_sec = htonl(fr->duration_sec);
nfr->duration_nsec = htonl(fr->duration_nsec);
nfr->idle_timeout = htons(fr->idle_timeout);
pin->fmd.in_port = match->flow.in_port;
pin->fmd.tun_id = match->flow.tunnel.tun_id;
+ pin->fmd.tun_src = match->flow.tunnel.ip_src;
+ pin->fmd.tun_dst = match->flow.tunnel.ip_dst;
pin->fmd.metadata = match->flow.metadata;
memcpy(pin->fmd.regs, match->flow.regs, sizeof pin->fmd.regs);
}
if (pin->fmd.tun_id != htonll(0)) {
match_set_tun_id(match, pin->fmd.tun_id);
}
+ if (pin->fmd.tun_src != htonl(0)) {
+ match_set_tun_src(match, pin->fmd.tun_src);
+ }
+ if (pin->fmd.tun_dst != htonl(0)) {
+ match_set_tun_dst(match, pin->fmd.tun_dst);
+ }
if (pin->fmd.metadata != htonll(0)) {
match_set_metadata(match, pin->fmd.metadata);
}
/* Converts the OpenFlow 1.1+ port number 'ofp11_port' into an OpenFlow 1.0
* port number and stores the latter in '*ofp10_port', for the purpose of
* decoding OpenFlow 1.1+ protocol messages. Returns 0 if successful,
- * otherwise an OFPERR_* number.
+ * otherwise an OFPERR_* number. On error, stores OFPP_NONE in '*ofp10_port'.
*
* See the definition of OFP11_MAX for an explanation of the mapping. */
enum ofperr
*ofp10_port = ofp11_port_h - OFPP11_OFFSET;
return 0;
} else {
+ *ofp10_port = OFPP_NONE;
VLOG_WARN_RL(&bad_ofmsg_rl, "port %"PRIu32" is outside the supported "
"range 0 through %d or 0x%"PRIx32" through 0x%"PRIx32,
ofp11_port_h, OFPP_MAX - 1,
int
ofputil_action_code_from_name(const char *name)
{
- static const char *names[OFPUTIL_N_ACTIONS] = {
+ static const char *const names[OFPUTIL_N_ACTIONS] = {
NULL,
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) NAME,
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME,
#include "ofp-util.def"
};
- const char **p;
+ const char *const *p;
for (p = names; p < &names[ARRAY_SIZE(names)]; p++) {
if (*p && !strcasecmp(name, *p)) {
* will be for Open Flow version 'ofp_version'. Returns message
* as a struct ofpbuf. Returns encoded message on success, NULL on error */
struct ofpbuf *
-ofputil_encode_dump_ports_request(enum ofp_version ofp_version, int16_t port)
+ofputil_encode_dump_ports_request(enum ofp_version ofp_version, uint16_t port)
{
struct ofpbuf *request;
struct ofp13_port_stats *ps13)
{
ofputil_port_stats_to_ofp11(ops, &ps13->ps);
-
- /* OF 1.3 adds duration fields */
- /* FIXME: Need to implement port alive duration (sec + nsec) */
- ps13->duration_sec = htonl(~0);
- ps13->duration_nsec = htonl(~0);
+ ps13->duration_sec = htonl(ops->duration_sec);
+ ps13->duration_nsec = htonl(ops->duration_nsec);
}
ops->stats.rx_over_errors = ntohll(get_32aligned_be64(&ps10->rx_over_err));
ops->stats.rx_crc_errors = ntohll(get_32aligned_be64(&ps10->rx_crc_err));
ops->stats.collisions = ntohll(get_32aligned_be64(&ps10->collisions));
+ ops->duration_sec = ops->duration_nsec = UINT32_MAX;
return 0;
}
ops->stats.rx_over_errors = ntohll(ps11->rx_over_err);
ops->stats.rx_crc_errors = ntohll(ps11->rx_crc_err);
ops->stats.collisions = ntohll(ps11->collisions);
+ ops->duration_sec = ops->duration_nsec = UINT32_MAX;
return 0;
}
ofputil_port_stats_from_ofp13(struct ofputil_port_stats *ops,
const struct ofp13_port_stats *ps13)
{
- enum ofperr error =
- ofputil_port_stats_from_ofp11(ops, &ps13->ps);
+ enum ofperr error = ofputil_port_stats_from_ofp11(ops, &ps13->ps);
if (!error) {
- /* FIXME: Get ps13->duration_sec and ps13->duration_nsec,
- * Add to netdev_stats? */
+ ops->duration_sec = ntohl(ps13->duration_sec);
+ ops->duration_nsec = ntohl(ps13->duration_nsec);
}
-
return error;
}