X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=1d0ab85e8955b55413f7b771f01e03571bc0c7f1;hb=f31282b9c152d5e993c8fe0068b7a4ed8c8d98c8;hp=557c95d808f080d7335f58415f4f21d83981459a;hpb=8dd546660e335e746eadb011481c66c5e4e30fde;p=sliver-openvswitch.git diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 557c95d80..1d0ab85e8 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -168,8 +168,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,22 +279,28 @@ parse_controller(struct ofpbuf *b, char *arg) } static void -parse_dec_ttl(struct ofpbuf *b, char *arg) +parse_noargs_dec_ttl(struct ofpbuf *b) { struct ofpact_cnt_ids *ids; + uint16_t id = 0; ids = ofpact_put_DEC_TTL(b); + ofpbuf_put(b, &id, sizeof id); + ids = b->l2; + ids->n_controllers++; + ofpact_update_len(b, &ids->ofpact); +} +static void +parse_dec_ttl(struct ofpbuf *b, char *arg) +{ if (*arg == '\0') { - uint16_t id = 0; - - ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL; - ofpbuf_put(b, &id, sizeof id); - ids = b->l2; - ids->n_controllers++; + parse_noargs_dec_ttl(b); } else { + struct ofpact_cnt_ids *ids; char *cntr; + ids = ofpact_put_DEC_TTL(b); ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL_CNT_IDS; for (cntr = strtok_r(arg, ", ", &arg); cntr != NULL; cntr = strtok_r(NULL, ", ", &arg)) { @@ -309,9 +314,8 @@ parse_dec_ttl(struct ofpbuf *b, char *arg) ovs_fatal(0, "dec_ttl_cnt_ids: expected at least one controller " "id."); } - + ofpact_update_len(b, &ids->ofpact); } - ofpact_update_len(b, &ids->ofpact); } static void @@ -356,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; @@ -398,9 +421,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); @@ -432,6 +470,9 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, ofpact_put_SET_IPV4_DSCP(ofpacts)->dscp = tos; break; + case OFPUTIL_OFPAT11_DEC_NW_TTL: + NOT_REACHED(); + case OFPUTIL_OFPAT10_SET_TP_SRC: case OFPUTIL_OFPAT11_SET_TP_SRC: ofpact_put_SET_L4_SRC_PORT(ofpacts)->port = str_to_u32(arg); @@ -457,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; @@ -537,8 +582,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); @@ -552,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; @@ -562,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); } @@ -569,24 +621,24 @@ 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; case OVSINST_OFPIT11_CLEAR_ACTIONS: - /* TODO:XXX */ - ovs_fatal(0, "instruction clear-actions is not supported yet"); + ofpact_put_CLEAR_ACTIONS(ofpacts); 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: { @@ -599,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 @@ -666,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++) { @@ -774,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"); @@ -803,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; @@ -814,8 +880,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); }