return 0;
}
+static enum ofperr
+sample_from_openflow(const struct nx_action_sample *nas,
+ struct ofpbuf *out)
+{
+ struct ofpact_sample *sample;
+
+ sample = ofpact_put_SAMPLE(out);
+ sample->probability = ntohs(nas->probability);
+ sample->collector_set_id = ntohl(nas->collector_set_id);
+ sample->obs_domain_id = ntohl(nas->obs_domain_id);
+ sample->obs_point_id = ntohl(nas->obs_point_id);
+
+ if (sample->probability == 0) {
+ return OFPERR_OFPBAC_BAD_ARGUMENT;
+ }
+
+ return 0;
+}
+
static enum ofperr
decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code)
{
ofpact_put_POP_MPLS(out)->ethertype = nxapm->ethertype;
break;
}
+
+ case OFPUTIL_NXAST_SAMPLE:
+ error = sample_from_openflow(
+ (const struct nx_action_sample *) a, out);
+ break;
}
return error;
return nxm_reg_move_check(ofpact_get_REG_MOVE(a), flow);
case OFPACT_REG_LOAD:
- if (*dl_type != flow->dl_type) {
- struct flow updated_flow = *flow;
- updated_flow.dl_type = *dl_type;
- return nxm_reg_load_check(ofpact_get_REG_LOAD(a), &updated_flow);
- } else {
- return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow);
- }
+ return nxm_reg_load_check(ofpact_get_REG_LOAD(a), flow);
case OFPACT_STACK_PUSH:
return nxm_stack_push_check(ofpact_get_STACK_PUSH(a), flow);
*dl_type = ofpact_get_POP_MPLS(a)->ethertype;
return 0;
+ case OFPACT_SAMPLE:
+ return 0;
+
case OFPACT_CLEAR_ACTIONS:
case OFPACT_WRITE_METADATA:
case OFPACT_GOTO_TABLE:
{
const struct ofpact *a;
ovs_be16 dl_type = flow->dl_type;
+ struct flow updated_flow;
OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
- enum ofperr error = ofpact_check__(a, flow, max_ports, &dl_type);
+ enum ofperr error;
+
+ /* If the dl_type was changed by an action then its new value
+ * should be present in the flow passed to ofpact_check__(). */
+ if (flow->dl_type != dl_type) {
+ /* Only copy flow at most once */
+ if (flow != &updated_flow) {
+ updated_flow = *flow;
+ flow = &updated_flow;
+ }
+ updated_flow.dl_type = dl_type;
+ }
+
+ error = ofpact_check__(a, flow, max_ports, &dl_type);
if (error) {
return error;
}
naft->fin_hard_timeout = htons(fin_timeout->fin_hard_timeout);
}
+static void
+ofpact_sample_to_nxast(const struct ofpact_sample *os,
+ struct ofpbuf *out)
+{
+ struct nx_action_sample *nas;
+
+ nas = ofputil_put_NXAST_SAMPLE(out);
+ nas->probability = htons(os->probability);
+ nas->collector_set_id = htonl(os->collector_set_id);
+ nas->obs_domain_id = htonl(os->obs_domain_id);
+ nas->obs_point_id = htonl(os->obs_point_id);
+}
+
static void
ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
{
ofpact_get_POP_MPLS(a)->ethertype;
break;
+ case OFPACT_SAMPLE:
+ ofpact_sample_to_nxast(ofpact_get_SAMPLE(a), out);
+ break;
+
case OFPACT_OUTPUT:
case OFPACT_ENQUEUE:
case OFPACT_SET_VLAN_VID:
case OFPACT_EXIT:
case OFPACT_PUSH_MPLS:
case OFPACT_POP_MPLS:
+ case OFPACT_SAMPLE:
ofpact_to_nxast(a, out);
break;
}
case OFPACT_MULTIPATH:
case OFPACT_NOTE:
case OFPACT_EXIT:
+ case OFPACT_SAMPLE:
ofpact_to_nxast(a, out);
break;
}
case OFPACT_EXIT:
case OFPACT_PUSH_MPLS:
case OFPACT_POP_MPLS:
+ case OFPACT_SAMPLE:
case OFPACT_CLEAR_ACTIONS:
case OFPACT_GOTO_TABLE:
default:
const struct ofpact_controller *controller;
const struct ofpact_metadata *metadata;
const struct ofpact_tunnel *tunnel;
+ const struct ofpact_sample *sample;
uint16_t port;
switch (a->type) {
ds_put_cstr(s, "exit");
break;
+ case OFPACT_SAMPLE:
+ sample = ofpact_get_SAMPLE(a);
+ ds_put_format(
+ s, "sample(probability=%"PRIu16",collector_set_id=%"PRIu32
+ ",obs_domain_id=%"PRIu32",obs_point_id=%"PRIu32")",
+ sample->probability, sample->collector_set_id,
+ sample->obs_domain_id, sample->obs_point_id);
+ break;
+
case OFPACT_CLEAR_ACTIONS:
ds_put_format(s, "%s",
ofpact_instruction_name_from_type(