#include "openflow/openflow.h"
#include "ovs-thread.h"
#include "packets.h"
+#include "simap.h"
#include "socket-util.h"
#include "vconn.h"
char *error = NULL;
uint16_t ethertype = 0;
uint16_t vid = 0;
- uint8_t tos = 0;
+ uint8_t tos = 0, ecn, ttl;
uint8_t pcp = 0;
switch (code) {
if (tos & ~IP_DSCP_MASK) {
return xasprintf("%s: not a valid TOS", arg);
}
- ofpact_put_SET_IPV4_DSCP(ofpacts)->dscp = tos;
+ ofpact_put_SET_IP_DSCP(ofpacts)->dscp = tos;
+ break;
+
+ case OFPUTIL_OFPAT11_SET_NW_ECN:
+ error = str_to_u8(arg, "ECN", &ecn);
+ if (error) {
+ return error;
+ }
+
+ if (ecn & ~IP_ECN_MASK) {
+ return xasprintf("%s: not a valid ECN", arg);
+ }
+ ofpact_put_SET_IP_ECN(ofpacts)->ecn = ecn;
+ break;
+
+ case OFPUTIL_OFPAT11_SET_NW_TTL:
+ error = str_to_u8(arg, "TTL", &ttl);
+ if (error) {
+ return error;
+ }
+
+ ofpact_put_SET_IP_TTL(ofpacts)->ttl = ttl;
break;
case OFPUTIL_OFPAT11_DEC_NW_TTL:
case OVSINST_OFPIT11_WRITE_ACTIONS: {
struct ofpact_nest *on;
- size_t ofs = ofpacts->size;
+ size_t ofs;
+ ofpact_pad(ofpacts);
+ ofs = ofpacts->size;
on = ofpact_put(ofpacts, OFPACT_WRITE_ACTIONS,
offsetof(struct ofpact_nest, actions));
error_s = str_to_ofpacts__(arg, ofpacts, usable_protocols);
/* Parses a specification of a flow from 's' into 'flow'. 's' must take the
* form FIELD=VALUE[,FIELD=VALUE]... where each FIELD is the name of a
* mf_field. Fields must be specified in a natural order for satisfying
- * prerequisites.
+ * prerequisites. If 'mask' is specified, fills the mask field for each of the
+ * field specified in flow. If the map, 'names_portno' is specfied, converts
+ * the in_port name into port no while setting the 'flow'.
*
* Returns NULL on success, otherwise a malloc()'d string that explains the
* problem. */
char *
-parse_ofp_exact_flow(struct flow *flow, const char *s)
+parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s,
+ const struct simap *portno_names)
{
char *pos, *key, *value_s;
char *error = NULL;
char *copy;
memset(flow, 0, sizeof *flow);
+ if (mask) {
+ memset(mask, 0, sizeof *mask);
+ }
pos = copy = xstrdup(s);
while (ofputil_parse_key_value(&pos, &key, &value_s)) {
goto exit;
}
flow->dl_type = htons(p->dl_type);
+ if (mask) {
+ mask->dl_type = OVS_BE16_MAX;
+ }
if (p->nw_proto) {
if (flow->nw_proto) {
goto exit;
}
flow->nw_proto = p->nw_proto;
+ if (mask) {
+ mask->nw_proto = UINT8_MAX;
+ }
}
} else {
const struct mf_field *mf;
goto exit;
}
- field_error = mf_parse_value(mf, value_s, &value);
- if (field_error) {
- error = xasprintf("%s: bad value for %s (%s)",
- s, key, field_error);
- free(field_error);
- goto exit;
- }
+ if (!strcmp(key, "in_port")
+ && portno_names
+ && simap_contains(portno_names, value_s)) {
+ flow->in_port.ofp_port = u16_to_ofp(
+ simap_get(portno_names, value_s));
+ if (mask) {
+ mask->in_port.ofp_port = u16_to_ofp(ntohs(OVS_BE16_MAX));
+ }
+ } else {
+ field_error = mf_parse_value(mf, value_s, &value);
+ if (field_error) {
+ error = xasprintf("%s: bad value for %s (%s)",
+ s, key, field_error);
+ free(field_error);
+ goto exit;
+ }
- mf_set_flow_value(mf, &value, flow);
+ mf_set_flow_value(mf, &value, flow);
+ if (mask) {
+ mf_mask_field(mf, mask);
+ }
+ }
}
}
if (error) {
memset(flow, 0, sizeof *flow);
+ if (mask) {
+ memset(mask, 0, sizeof *mask);
+ }
}
return error;
}