X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=40215511dad0729fc2a5d2070e60e0c616d71a37;hb=a5ac7299f8042c01fcdb60c5508047146baf3a16;hp=a80d45fe62608d12a653856dc8fbf233c6d54b5d;hpb=6a885fd0589fdfa3b5d05ca3ff4af52b085a1816;p=openvswitch diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index a80d45fe..40215511 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -26,6 +26,7 @@ #include "bundle.h" #include "byte-order.h" #include "dynamic-string.h" +#include "learn.h" #include "meta-flow.h" #include "netdev.h" #include "multipath.h" @@ -40,6 +41,28 @@ VLOG_DEFINE_THIS_MODULE(ofp_parse); +static uint8_t +str_to_table_id(const char *str) +{ + int table_id; + + if (!str_to_int(str, 10, &table_id) || table_id < 0 || table_id > 255) { + ovs_fatal(0, "invalid table \"%s\"", str); + } + return table_id; +} + +static uint16_t +str_to_u16(const char *str, const char *name) +{ + int value; + + if (!str_to_int(str, 0, &value) || value < 0 || value > 65535) { + ovs_fatal(0, "invalid %s \"%s\"", name, str); + } + return value; +} + static uint32_t str_to_u32(const char *str) { @@ -228,7 +251,8 @@ parse_note(struct ofpbuf *b, const char *arg) } static void -parse_named_action(enum ofputil_action_code code, struct ofpbuf *b, char *arg) +parse_named_action(enum ofputil_action_code code, const struct flow *flow, + struct ofpbuf *b, char *arg) { struct ofp_action_dl_addr *oada; struct ofp_action_vlan_pcp *oavp; @@ -332,11 +356,19 @@ parse_named_action(enum ofputil_action_code code, struct ofpbuf *b, char *arg) case OFPUTIL_NXAST_RESUBMIT_TABLE: case OFPUTIL_NXAST_OUTPUT_REG: NOT_REACHED(); + + case OFPUTIL_NXAST_LEARN: + learn_parse(b, arg, flow); + break; + + case OFPUTIL_NXAST_EXIT: + ofputil_put_NXAST_EXIT(b); + break; } } static void -str_to_action(char *str, struct ofpbuf *b) +str_to_action(const struct flow *flow, char *str, struct ofpbuf *b) { char *pos, *act, *arg; int n_actions; @@ -349,7 +381,7 @@ str_to_action(char *str, struct ofpbuf *b) code = ofputil_action_code_from_name(act); if (code >= 0) { - parse_named_action(code, b, arg); + parse_named_action(code, flow, b, arg); } else if (!strcasecmp(act, "drop")) { /* A drop action in OpenFlow occurs by just not setting * an action. */ @@ -462,6 +494,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, } fields; char *string = xstrdup(str_); char *save_ptr = NULL; + char *act_str = NULL; char *name; switch (command) { @@ -503,9 +536,6 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, fm->out_port = OFPP_NONE; fm->flags = 0; if (fields & F_ACTIONS) { - struct ofpbuf actions; - char *act_str; - act_str = strstr(string, "action"); if (!act_str) { ofp_fatal(str_, verbose, "must specify an action"); @@ -518,14 +548,6 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, } act_str++; - - ofpbuf_init(&actions, sizeof(union ofp_action)); - str_to_action(act_str, &actions); - fm->actions = ofpbuf_steal_data(&actions); - fm->n_actions = actions.size / sizeof(union ofp_action); - } else { - fm->actions = NULL; - fm->n_actions = 0; } for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name; name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) { @@ -545,15 +567,15 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, } if (!strcmp(name, "table")) { - fm->table_id = atoi(value); + fm->table_id = str_to_table_id(value); } else if (!strcmp(name, "out_port")) { fm->out_port = atoi(value); } else if (fields & F_PRIORITY && !strcmp(name, "priority")) { - fm->cr.priority = atoi(value); + fm->cr.priority = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) { - fm->idle_timeout = atoi(value); + fm->idle_timeout = str_to_u16(value, name); } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) { - fm->hard_timeout = atoi(value); + fm->hard_timeout = str_to_u16(value, name); } else if (fields & F_COOKIE && !strcmp(name, "cookie")) { fm->cookie = htonll(str_to_u64(value)); } else if (mf_from_name(name)) { @@ -569,6 +591,17 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, } } } + if (fields & F_ACTIONS) { + struct ofpbuf actions; + + ofpbuf_init(&actions, sizeof(union ofp_action)); + str_to_action(&fm->cr.flow, act_str, &actions); + fm->actions = ofpbuf_steal_data(&actions); + fm->n_actions = actions.size / sizeof(union ofp_action); + } else { + fm->actions = NULL; + fm->n_actions = 0; + } free(string); } @@ -586,11 +619,9 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format, { enum nx_flow_format min_format, next_format; struct cls_rule rule_copy; - struct ofpbuf actions; struct ofpbuf *ofm; struct ofputil_flow_mod fm; - ofpbuf_init(&actions, 64); parse_ofp_str(&fm, command, string, verbose); min_format = ofputil_min_flow_format(&fm.cr); @@ -615,8 +646,6 @@ parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format, ofm = ofputil_encode_flow_mod(&fm, *cur_format, *flow_mod_table_id); list_push_back(packets, &ofm->list_node); - - ofpbuf_uninit(&actions); } /* Similar to parse_ofp_flow_mod_str(), except that the string is read from