X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=1d0ab85e8955b55413f7b771f01e03571bc0c7f1;hb=f31282b9c152d5e993c8fe0068b7a4ed8c8d98c8;hp=a9d70de1099da881d90076bbedd785ba4627d33b;hpb=68194f84b13011742cca3dc1b55d86c1c60a9555;p=sliver-openvswitch.git diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index a9d70de10..1d0ab85e8 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -279,13 +279,12 @@ parse_controller(struct ofpbuf *b, char *arg) } static void -parse_noargs_dec_ttl(struct ofpbuf *b, enum ofputil_action_code compat) +parse_noargs_dec_ttl(struct ofpbuf *b) { struct ofpact_cnt_ids *ids; uint16_t id = 0; ids = ofpact_put_DEC_TTL(b); - ids->ofpact.compat = compat; ofpbuf_put(b, &id, sizeof id); ids = b->l2; ids->n_controllers++; @@ -293,10 +292,10 @@ parse_noargs_dec_ttl(struct ofpbuf *b, enum ofputil_action_code compat) } static void -parse_dec_ttl(struct ofpbuf *b, char *arg, enum ofputil_action_code compat) +parse_dec_ttl(struct ofpbuf *b, char *arg) { if (*arg == '\0') { - parse_noargs_dec_ttl(b, compat); + parse_noargs_dec_ttl(b); } else { struct ofpact_cnt_ids *ids; char *cntr; @@ -361,12 +360,31 @@ set_field_parse(const char *arg, struct ofpbuf *ofpacts) free(orig); } +static void +parse_metadata(struct ofpbuf *b, char *arg) +{ + struct ofpact_metadata *om; + char *mask = strchr(arg, '/'); + + om = ofpact_put_WRITE_METADATA(b); + + if (mask) { + *mask = '\0'; + om->mask = htonll(str_to_u64(mask + 1)); + } else { + om->mask = htonll(UINT64_MAX); + } + + om->metadata = htonll(str_to_u64(arg)); +} + static void parse_named_action(enum ofputil_action_code code, const struct flow *flow, char *arg, struct ofpbuf *ofpacts) { struct ofpact_tunnel *tunnel; uint16_t vid; + uint16_t ethertype; ovs_be32 ip; uint8_t pcp; uint8_t tos; @@ -407,6 +425,20 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, ofpact_put_STRIP_VLAN(ofpacts); break; + case OFPUTIL_OFPAT11_PUSH_VLAN: + ethertype = str_to_u16(arg, "ethertype"); + if (ethertype != ETH_TYPE_VLAN_8021Q) { + /* XXX ETH_TYPE_VLAN_8021AD case isn't supported */ + ovs_fatal(0, "%s: not a valid VLAN ethertype", arg); + } + ofpact_put_PUSH_VLAN(ofpacts); + break; + + case OFPUTIL_OFPAT11_SET_QUEUE: + ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg); + break; + + case OFPUTIL_OFPAT10_SET_DL_SRC: case OFPUTIL_OFPAT11_SET_DL_SRC: str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac); @@ -466,6 +498,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, tunnel->tun_id = str_to_u64(arg); break; + case OFPUTIL_NXAST_WRITE_METADATA: + parse_metadata(ofpacts, arg); + break; + case OFPUTIL_NXAST_SET_QUEUE: ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg); break; @@ -516,7 +552,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, break; case OFPUTIL_NXAST_DEC_TTL: - parse_dec_ttl(ofpacts, arg, code); + parse_dec_ttl(ofpacts, arg); break; case OFPUTIL_NXAST_FIN_TIMEOUT: @@ -561,6 +597,7 @@ static void str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts) { char *pos, *act, *arg; + enum ofperr error; int n_actions; pos = str; @@ -571,6 +608,12 @@ str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts) } n_actions++; } + + error = ofpacts_verify(ofpacts->data, ofpacts->size); + if (error) { + ovs_fatal(0, "Incorrect action ordering"); + } + ofpact_pad(ofpacts); } @@ -578,13 +621,15 @@ static void parse_named_instruction(enum ovs_instruction_type type, char *arg, struct ofpbuf *ofpacts) { + enum ofperr error; + switch (type) { case OVSINST_OFPIT11_APPLY_ACTIONS: NOT_REACHED(); /* This case is handled by str_to_inst_ofpacts() */ break; case OVSINST_OFPIT11_WRITE_ACTIONS: - /* TODO:XXX */ + /* XXX */ ovs_fatal(0, "instruction write-actions is not supported yet"); break; @@ -593,8 +638,7 @@ parse_named_instruction(enum ovs_instruction_type type, break; case OVSINST_OFPIT11_WRITE_METADATA: - /* TODO:XXX */ - ovs_fatal(0, "instruction write-metadata is not supported yet"); + parse_metadata(ofpacts, arg); break; case OVSINST_OFPIT11_GOTO_TABLE: { @@ -607,6 +651,13 @@ parse_named_instruction(enum ovs_instruction_type type, break; } } + + /* If write_metadata is specified as an action AND an instruction, ofpacts + could be invalid. */ + error = ofpacts_verify(ofpacts->data, ofpacts->size); + if (error) { + ovs_fatal(0, "Incorrect instruction ordering"); + } } static void @@ -674,7 +725,8 @@ parse_protocol(const char *name, const struct protocol **p_out) { "icmp6", ETH_TYPE_IPV6, IPPROTO_ICMPV6 }, { "tcp6", ETH_TYPE_IPV6, IPPROTO_TCP }, { "udp6", ETH_TYPE_IPV6, IPPROTO_UDP }, - }; + { "rarp", ETH_TYPE_RARP, 0}, +}; const struct protocol *p; for (p = protocols; p < &protocols[ARRAY_SIZE(protocols)]; p++) { @@ -782,7 +834,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, fm->idle_timeout = OFP_FLOW_PERMANENT; fm->hard_timeout = OFP_FLOW_PERMANENT; fm->buffer_id = UINT32_MAX; - fm->out_port = OFPP_NONE; + fm->out_port = OFPP_ANY; fm->flags = 0; if (fields & F_ACTIONS) { act_str = strstr(string, "action"); @@ -811,6 +863,12 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, fm->flags |= OFPFF_SEND_FLOW_REM; } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) { fm->flags |= OFPFF_CHECK_OVERLAP; + } else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) { + fm->flags |= OFPFF12_RESET_COUNTS; + } else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) { + fm->flags |= OFPFF13_NO_PKT_COUNTS; + } else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) { + fm->flags |= OFPFF13_NO_BYT_COUNTS; } else { char *value;