}
/* Given the IP netmask 'netmask', returns the number of bits of the IP address
- * that it wildcards, that is, the number of 0-bits in 'netmask'. 'netmask'
- * must be a CIDR netmask (see ip_is_cidr()). */
+ * that it wildcards, that is, the number of 0-bits in 'netmask', a number
+ * between 0 and 32 inclusive.
+ *
+ * If 'netmask' is not a CIDR netmask (see ip_is_cidr()), the return value will
+ * still be in the valid range but isn't otherwise meaningful. */
int
ofputil_netmask_to_wcbits(ovs_be32 netmask)
{
void
ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
/* Initialize most of rule->wc. */
flow_wildcards_init_catchall(wc);
if (!(wc & OFPFW11_NW_PROTO)) {
cls_rule_set_nw_proto(rule, match->nw_proto);
}
-
- if (!ip_is_cidr(~match->nw_src_mask) ||
- !ip_is_cidr(~match->nw_dst_mask)) {
- return OFPERR_OFPBMC_BAD_NW_ADDR_MASK;
- }
cls_rule_set_nw_src_masked(rule, match->nw_src, ~match->nw_src_mask);
cls_rule_set_nw_dst_masked(rule, match->nw_dst, ~match->nw_dst_mask);
}
}
if (match->metadata_mask != htonll(UINT64_MAX)) {
- /* Metadata field not yet supported because we haven't decided how to
- * map it onto our existing fields (or whether to add a new field). */
- return OFPERR_OFPBMC_BAD_FIELD;
+ cls_rule_set_metadata_masked(rule, match->metadata,
+ ~match->metadata_mask);
}
return 0;
wc |= OFPFW11_MPLS_LABEL;
wc |= OFPFW11_MPLS_TC;
- /* Metadata field not yet supported */
- match->metadata_mask = htonll(UINT64_MAX);
+ match->metadata = rule->flow.metadata;
+ match->metadata_mask = ~rule->wc.metadata_mask;
match->wildcards = htonl(wc);
}
sizeof(struct ofp_port_status) + sizeof(struct ofp11_port), 0 },
{ OFPUTIL_OFPT_PACKET_OUT, OFP10_VERSION,
- OFPT10_PACKET_OUT, "OFPT_PACKET_OUT",
+ OFPT_PACKET_OUT, "OFPT_PACKET_OUT",
sizeof(struct ofp_packet_out), 1 },
{ OFPUTIL_OFPT_FLOW_MOD, OFP10_VERSION,
- OFPT10_FLOW_MOD, "OFPT_FLOW_MOD",
+ OFPT_FLOW_MOD, "OFPT_FLOW_MOD",
sizeof(struct ofp_flow_mod), 1 },
{ OFPUTIL_OFPT_PORT_MOD, OFP10_VERSION,
{
const struct flow_wildcards *wc = &rule->wc;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 11);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 12);
/* NXM and OF1.1+ supports bitwise matching on ethernet addresses. */
if (!eth_mask_is_exact(wc->dl_src_mask)
return OFPUTIL_P_NXM_ANY;
}
+ /* NXM and OF1.1+ support matching metadata. */
+ if (wc->metadata_mask != htonll(0)) {
+ return OFPUTIL_P_NXM_ANY;
+ }
+
/* Only NXM supports matching ARP hardware addresses. */
if (!(wc->wildcards & FWW_ARP_SHA) || !(wc->wildcards & FWW_ARP_THA)) {
return OFPUTIL_P_NXM_ANY;
return OFPUTIL_P_NXM_ANY;
}
+ /* Only NXM supports non-CIDR IPv4 address masks. */
+ if (!ip_is_cidr(wc->nw_src_mask) || !ip_is_cidr(wc->nw_dst_mask)) {
+ return OFPUTIL_P_NXM_ANY;
+ }
+
/* Only NXM supports bitwise matching on transport port. */
if ((wc->tp_src_mask && wc->tp_src_mask != htons(UINT16_MAX)) ||
(wc->tp_dst_mask && wc->tp_dst_mask != htons(UINT16_MAX))) {
case OFPUTIL_P_OF10:
case OFPUTIL_P_OF10_TID:
msg = ofpbuf_new(sizeof *ofm + actions_len);
- ofm = put_openflow(sizeof *ofm, OFPT10_FLOW_MOD, msg);
+ ofm = put_openflow(sizeof *ofm, OFPT_FLOW_MOD, msg);
ofputil_cls_rule_to_ofp10_match(&fm->cr, &ofm->match);
ofm->cookie = fm->new_cookie;
ofm->command = htons(command);
nfm->cookie = fm->new_cookie;
match_len = nx_put_match(msg, false, &fm->cr,
fm->cookie, fm->cookie_mask);
+ nfm = msg->data;
nfm->idle_timeout = htons(fm->idle_timeout);
nfm->hard_timeout = htons(fm->hard_timeout);
nfm->priority = htons(fm->cr.priority);
return msg;
}
-int
+enum ofperr
ofputil_decode_packet_in(struct ofputil_packet_in *pin,
const struct ofp_header *oh)
{
pin->fmd.tun_id = rule.flow.tun_id;
pin->fmd.tun_id_mask = rule.wc.tun_id_mask;
+ pin->fmd.metadata = rule.flow.metadata;
+ pin->fmd.metadata_mask = rule.wc.metadata_mask;
+
memcpy(pin->fmd.regs, rule.flow.regs, sizeof pin->fmd.regs);
memcpy(pin->fmd.reg_masks, rule.wc.reg_masks,
sizeof pin->fmd.reg_masks);
cls_rule_init_catchall(&rule, 0);
cls_rule_set_tun_id_masked(&rule, pin->fmd.tun_id,
pin->fmd.tun_id_mask);
+ cls_rule_set_metadata_masked(&rule, pin->fmd.metadata,
+ pin->fmd.metadata_mask);
+
for (i = 0; i < FLOW_N_REGS; i++) {
cls_rule_set_reg_masked(&rule, i, pin->fmd.regs[i],
}
msg = ofpbuf_new(size);
- opo = put_openflow(sizeof *opo, OFPT10_PACKET_OUT, msg);
+ opo = put_openflow(sizeof *opo, OFPT_PACKET_OUT, msg);
opo->buffer_id = htonl(po->buffer_id);
opo->in_port = htons(po->in_port);
opo->actions_len = htons(actions_len);
struct ofpbuf *out = ofpbuf_new(size);
ofm = ofpbuf_put_zeros(out, sizeof *ofm);
ofm->header.version = OFP10_VERSION;
- ofm->header.type = OFPT10_FLOW_MOD;
+ ofm->header.type = OFPT_FLOW_MOD;
ofm->header.length = htons(size);
ofm->cookie = 0;
ofm->priority = htons(MIN(rule->priority, UINT16_MAX));
return out;
}
-struct ofpbuf *
-make_del_flow(const struct cls_rule *rule)
-{
- struct ofpbuf *out = make_flow_mod(OFPFC_DELETE_STRICT, rule, 0);
- struct ofp_flow_mod *ofm = out->data;
- ofm->out_port = htons(OFPP_NONE);
- return out;
-}
-
-struct ofpbuf *
-make_add_simple_flow(const struct cls_rule *rule,
- uint32_t buffer_id, uint16_t out_port,
- uint16_t idle_timeout)
-{
- if (out_port != OFPP_NONE) {
- struct ofp_action_output *oao;
- struct ofpbuf *buffer;
-
- buffer = make_add_flow(rule, buffer_id, idle_timeout, sizeof *oao);
- ofputil_put_OFPAT10_OUTPUT(buffer)->port = htons(out_port);
- return buffer;
- } else {
- return make_add_flow(rule, buffer_id, idle_timeout, 0);
- }
-}
-
struct ofpbuf *
make_packet_in(uint32_t buffer_id, uint16_t in_port, uint8_t reason,
const struct ofpbuf *payload, int max_send_len)
error = 0;
switch ((enum ofputil_action_code) code) {
+ case OFPUTIL_ACTION_INVALID:
+ NOT_REACHED();
+
case OFPUTIL_OFPAT10_OUTPUT:
error = ofputil_check_output_port(ntohs(a->output.port),
max_ports);
ofputil_action_code_from_name(const char *name)
{
static const char *names[OFPUTIL_N_ACTIONS] = {
+ NULL,
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) NAME,
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME,
#include "ofp-util.def"
ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf)
{
switch (code) {
+ case OFPUTIL_ACTION_INVALID:
+ NOT_REACHED();
+
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \