rule->flow.nw_proto = match->nw_proto;
/* Translate VLANs. */
- if (!(ofpfw & OFPFW10_DL_VLAN) && match->dl_vlan == htons(OFP_VLAN_NONE)) {
+ if (!(ofpfw & OFPFW10_DL_VLAN) &&
+ match->dl_vlan == htons(OFP10_VLAN_NONE)) {
/* Match only packets without 802.1Q header.
*
* When OFPFW10_DL_VLAN_PCP is wildcarded, this is obviously correct.
ofpfw |= OFPFW10_DL_VLAN | OFPFW10_DL_VLAN_PCP;
} else if (rule->wc.vlan_tci_mask & htons(VLAN_CFI)
&& !(rule->flow.vlan_tci & htons(VLAN_CFI))) {
- match->dl_vlan = htons(OFP_VLAN_NONE);
+ match->dl_vlan = htons(OFP10_VLAN_NONE);
} else {
if (!(rule->wc.vlan_tci_mask & htons(VLAN_VID_MASK))) {
ofpfw |= OFPFW10_DL_VLAN;
ofputil_normalize_rule(&fm->cr);
/* Now get the actions. */
- error = ofpacts_pull_openflow(&b, b.size, ofpacts);
+ error = ofpacts_pull_openflow10(&b, b.size, ofpacts);
if (error) {
return error;
}
if (error) {
return error;
}
- error = ofpacts_pull_openflow(&b, b.size, ofpacts);
+ error = ofpacts_pull_openflow10(&b, b.size, ofpacts);
if (error) {
return error;
}
}
if (fm->ofpacts) {
- ofpacts_to_openflow(fm->ofpacts, fm->ofpacts_len, msg);
+ ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
}
update_openflow_length(msg);
return msg;
return EINVAL;
}
- if (ofpacts_pull_openflow(msg, length - sizeof *ofs, ofpacts)) {
+ if (ofpacts_pull_openflow10(msg, length - sizeof *ofs, ofpacts)) {
return EINVAL;
}
}
actions_len = length - sizeof *nfs - ROUND_UP(match_len, 8);
- if (ofpacts_pull_openflow(msg, actions_len, ofpacts)) {
+ if (ofpacts_pull_openflow10(msg, actions_len, ofpacts)) {
return EINVAL;
}
if (osm->type == htons(OFPST_FLOW)) {
struct ofp_flow_stats *ofs;
- ofs = ofpbuf_put_uninit(reply, sizeof *ofs);
+ ofpbuf_put_uninit(reply, sizeof *ofs);
+ ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
+
+ ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
+ ofs->length = htons(reply->size - start_ofs);
ofs->table_id = fs->table_id;
ofs->pad = 0;
ofputil_cls_rule_to_ofp10_match(&fs->rule, &ofs->match);
htonll(unknown_to_zero(fs->packet_count)));
put_32aligned_be64(&ofs->byte_count,
htonll(unknown_to_zero(fs->byte_count)));
- ofpacts_to_openflow(fs->ofpacts, fs->ofpacts_len, reply);
-
- ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
- ofs->length = htons(reply->size - start_ofs);
} else if (osm->type == htons(OFPST_VENDOR)) {
struct nx_flow_stats *nfs;
+ int match_len;
- nfs = ofpbuf_put_uninit(reply, sizeof *nfs);
+ ofpbuf_put_uninit(reply, sizeof *nfs);
+ match_len = nx_put_match(reply, false, &fs->rule, 0, 0);
+ ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
+
+ nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
+ nfs->length = htons(reply->size - start_ofs);
nfs->table_id = fs->table_id;
nfs->pad = 0;
nfs->duration_sec = htonl(fs->duration_sec);
nfs->hard_age = htons(fs->hard_age < 0 ? 0
: fs->hard_age < UINT16_MAX ? fs->hard_age + 1
: UINT16_MAX);
- nfs->match_len = htons(nx_put_match(reply, false, &fs->rule, 0, 0));
+ nfs->match_len = htons(match_len);
nfs->cookie = fs->cookie;
nfs->packet_count = htonll(fs->packet_count);
nfs->byte_count = htonll(fs->byte_count);
- ofpacts_to_openflow(fs->ofpacts, fs->ofpacts_len, reply);
-
- nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
- nfs->length = htons(reply->size - start_ofs);
} else {
NOT_REACHED();
}
ofpbuf_use_const(&b, opo, ntohs(opo->header.length));
ofpbuf_pull(&b, sizeof *opo);
- error = ofpacts_pull_openflow(&b, ntohs(opo->actions_len), ofpacts);
+ error = ofpacts_pull_openflow10(&b, ntohs(opo->actions_len), ofpacts);
if (error) {
return error;
}
msg = ofpbuf_new(size);
put_openflow(sizeof *opo, OFPT_PACKET_OUT, msg);
- ofpacts_to_openflow(po->ofpacts, po->ofpacts_len, msg);
+ ofpacts_put_openflow10(po->ofpacts, po->ofpacts_len, msg);
opo = msg->data;
opo->buffer_id = htonl(po->buffer_id);
oh->length = htons(buffer->size);
}
-static void
-put_stats__(ovs_be32 xid, uint8_t ofp_type,
- ovs_be16 ofpst_type, ovs_be32 nxst_subtype,
- struct ofpbuf *msg)
+void
+ofputil_put_stats_header(ovs_be32 xid, uint8_t ofp_type,
+ ovs_be16 ofpst_type, ovs_be32 nxst_subtype,
+ struct ofpbuf *msg)
{
if (ofpst_type == htons(OFPST_VENDOR)) {
struct nicira_stats_msg *nsm;
struct ofpbuf *msg;
msg = *bufferp = ofpbuf_new(openflow_len);
- put_stats__(alloc_xid(), OFPT10_STATS_REQUEST,
- htons(ofpst_type), htonl(nxst_subtype), msg);
+ ofputil_put_stats_header(alloc_xid(), OFPT10_STATS_REQUEST,
+ htons(ofpst_type), htonl(nxst_subtype), msg);
ofpbuf_padto(msg, openflow_len);
return msg->data;
static void
put_stats_reply__(const struct ofp_stats_msg *request, struct ofpbuf *msg)
{
+ ovs_be32 nxst_subtype;
+
assert(request->header.type == OFPT10_STATS_REQUEST ||
request->header.type == OFPT10_STATS_REPLY);
- put_stats__(request->header.xid, OFPT10_STATS_REPLY, request->type,
- (request->type != htons(OFPST_VENDOR)
- ? htonl(0)
- : ((const struct nicira_stats_msg *) request)->subtype),
- msg);
+
+ nxst_subtype = (request->type != htons(OFPST_VENDOR)
+ ? htonl(0)
+ : ((const struct nicira_stats_msg *) request)->subtype);
+ ofputil_put_stats_header(request->header.xid, OFPT10_STATS_REPLY,
+ request->type, nxst_subtype, msg);
}
/* Creates a statistics reply message with total length 'openflow_len'
return ofpbuf_put_uninit(ofputil_reserve_stats_reply(len, replies), len);
}
+/* Sometimes, when composing stats replies, it's difficult to predict how long
+ * an individual reply chunk will be before actually encoding it into the reply
+ * buffer. This function allows easy handling of this case: just encode the
+ * reply, then use this function to break the message into two pieces if it
+ * exceeds the OpenFlow message limit.
+ *
+ * In detail, if the final stats message in 'replies' is too long for OpenFlow,
+ * this function breaks it into two separate stats replies, the first one with
+ * the first 'start_ofs' bytes, the second one containing the bytes from that
+ * offset onward. */
void
ofputil_postappend_stats_reply(size_t start_ofs, struct list *replies)
{
{
static const char *names[OFPUTIL_N_ACTIONS] = {
NULL,
-#define OFPAT10_ACTION(ENUM, STRUCT, NAME) NAME,
+#define OFPAT10_ACTION(ENUM, STRUCT, NAME) NAME,
+#define OFPAT11_ACTION(ENUM, STRUCT, NAME) NAME,
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) NAME,
#include "ofp-util.def"
};
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
+#define OFPAT11_ACTION OFPAT10_ACTION
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#include "ofp-util.def"
ofputil_init_##ENUM(s); \
return s; \
}
+#define OFPAT11_ACTION OFPAT10_ACTION
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \