X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=e8abc9f6d246f7d98d3e090ed32889622e64f072;hb=780325b5b8d4c0552b4b7719e0a38200d99f6b08;hp=ea0703a3819303df26ca2b3ccfb581f7b1971c22;hpb=7bcb1506ee2de6a460db35404e642f21d8219b5f;p=sliver-openvswitch.git diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index ea0703a38..e8abc9f6d 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -22,7 +22,6 @@ #include #include -#include "autopath.h" #include "bundle.h" #include "byte-order.h" #include "dynamic-string.h" @@ -168,8 +167,7 @@ parse_resubmit(char *arg, struct ofpbuf *ofpacts) in_port_s = strsep(&arg, ","); if (in_port_s && in_port_s[0]) { - resubmit->in_port = ofputil_port_from_string(in_port_s); - if (!resubmit->in_port) { + if (!ofputil_port_from_string(in_port_s, &resubmit->in_port)) { ovs_fatal(0, "%s: resubmit to unknown port", in_port_s); } } else { @@ -280,13 +278,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++; @@ -294,10 +291,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; @@ -320,6 +317,18 @@ parse_dec_ttl(struct ofpbuf *b, char *arg, enum ofputil_action_code compat) } } +static void +parse_set_mpls_ttl(struct ofpbuf *b, const char *arg) +{ + struct ofpact_mpls_ttl *mpls_ttl = ofpact_put_SET_MPLS_TTL(b); + + if (*arg == '\0') { + ovs_fatal(0, "parse_set_mpls_ttl: expected ttl."); + } + + mpls_ttl->ttl = atoi(arg); +} + static void set_field_parse(const char *arg, struct ofpbuf *ofpacts) { @@ -362,12 +371,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; @@ -404,9 +432,24 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, break; case OFPUTIL_OFPAT10_STRIP_VLAN: + case OFPUTIL_OFPAT11_POP_VLAN: 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); @@ -439,8 +482,7 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, break; case OFPUTIL_OFPAT11_DEC_NW_TTL: - parse_noargs_dec_ttl(ofpacts, code); - break; + NOT_REACHED(); case OFPUTIL_OFPAT10_SET_TP_SRC: case OFPUTIL_OFPAT11_SET_TP_SRC: @@ -467,6 +509,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; @@ -491,10 +537,6 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg); break; - case OFPUTIL_NXAST_AUTOPATH__DEPRECATED: - autopath_parse(ofpact_put_AUTOPATH(ofpacts), arg); - break; - case OFPUTIL_NXAST_BUNDLE: bundle_parse(arg, ofpacts); break; @@ -517,7 +559,17 @@ 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_SET_MPLS_TTL: + case OFPUTIL_OFPAT11_SET_MPLS_TTL: + parse_set_mpls_ttl(ofpacts, arg); + break; + + case OFPUTIL_OFPAT11_DEC_MPLS_TTL: + case OFPUTIL_NXAST_DEC_MPLS_TTL: + ofpact_put_DEC_MPLS_TTL(ofpacts); break; case OFPUTIL_NXAST_FIN_TIMEOUT: @@ -527,6 +579,24 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, case OFPUTIL_NXAST_CONTROLLER: parse_controller(ofpacts, arg); break; + + case OFPUTIL_OFPAT11_PUSH_MPLS: + case OFPUTIL_NXAST_PUSH_MPLS: + ofpact_put_PUSH_MPLS(ofpacts)->ethertype = + htons(str_to_u16(arg, "push_mpls")); + break; + + case OFPUTIL_OFPAT11_POP_MPLS: + case OFPUTIL_NXAST_POP_MPLS: + ofpact_put_POP_MPLS(ofpacts)->ethertype = + htons(str_to_u16(arg, "pop_mpls")); + break; + case OFPUTIL_NXAST_STACK_PUSH: + nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg); + break; + case OFPUTIL_NXAST_STACK_POP: + nxm_parse_stack_action(ofpact_put_STACK_POP(ofpacts), arg); + break; } } @@ -547,8 +617,8 @@ str_to_ofpact__(const struct flow *flow, char *pos, char *act, char *arg, } return false; } else { - uint16_t port = ofputil_port_from_string(act); - if (port) { + uint16_t port; + if (ofputil_port_from_string(act, &port)) { ofpact_put_OUTPUT(ofpacts)->port = port; } else { ovs_fatal(0, "Unknown action: %s", act); @@ -562,6 +632,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; @@ -572,6 +643,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); } @@ -579,13 +656,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; @@ -594,8 +673,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: { @@ -608,6 +686,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 @@ -675,6 +760,9 @@ 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}, + { "mpls", ETH_TYPE_MPLS, 0 }, + { "mplsm", ETH_TYPE_MPLS_MCAST, 0 }, }; const struct protocol *p; @@ -783,7 +871,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"); @@ -812,6 +900,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; @@ -823,8 +917,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, if (!strcmp(name, "table")) { fm->table_id = str_to_table_id(value); } else if (!strcmp(name, "out_port")) { - fm->out_port = ofputil_port_from_string(name); - if (!fm->out_port) { + if (!ofputil_port_from_string(name, &fm->out_port)) { ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port", name); } @@ -858,7 +951,9 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, parse_field(mf_from_name(name), value, &fm->match); } else if (!strcmp(name, "duration") || !strcmp(name, "n_packets") - || !strcmp(name, "n_bytes")) { + || !strcmp(name, "n_bytes") + || !strcmp(name, "idle_age") + || !strcmp(name, "hard_age")) { /* Ignore these, so that users can feed the output of * "ovs-ofctl dump-flows" back into commands that parse * flows. */ @@ -1093,6 +1188,10 @@ parse_ofp_exact_flow(struct flow *flow, const char *s) } } + if (!flow->in_port) { + flow->in_port = OFPP_NONE; + } + exit: free(copy);