X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=7fed553eadc0aa8fde0e434a11c8c21f8a7918b6;hb=b46ccdf582946f30d80735345c533c23a7f035c0;hp=1c7ce4fcff83ca9c594daee0790401b3a6e78562;hpb=f393f81e425658cdfddf29ca23086bf66d6b733c;p=openvswitch diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 1c7ce4fc..7fed553e 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Nicira Networks. + * Copyright (c) 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ #include "byte-order.h" #include "dynamic-string.h" #include "netdev.h" +#include "multipath.h" #include "nx-match.h" #include "ofp-util.h" #include "ofpbuf.h" @@ -127,6 +128,35 @@ str_to_ip(const char *str_, ovs_be32 *ip, ovs_be32 *maskp) free(str); } +static void +str_to_tun_id(const char *str, ovs_be64 *tun_idp, ovs_be64 *maskp) +{ + uint64_t tun_id, mask; + char *tail; + + errno = 0; + tun_id = strtoull(str, &tail, 0); + if (errno || (*tail != '\0' && *tail != '/')) { + goto error; + } + + if (*tail == '/') { + mask = strtoull(tail + 1, &tail, 0); + if (errno || *tail != '\0') { + goto error; + } + } else { + mask = UINT64_MAX; + } + + *tun_idp = htonll(tun_id); + *maskp = htonll(mask); + return; + +error: + ovs_fatal(0, "%s: bad syntax for tunnel id", str); +} + static void * put_action(struct ofpbuf *b, size_t size, uint16_t type) { @@ -194,26 +224,66 @@ parse_port_name(const char *name, uint16_t *port) static void str_to_action(char *str, struct ofpbuf *b) { - char *act, *arg; - char *saveptr = NULL; bool drop = false; int n_actions; + char *pos; - for (act = strtok_r(str, ", \t\r\n", &saveptr), n_actions = 0; act; - act = strtok_r(NULL, ", \t\r\n", &saveptr), n_actions++) - { + pos = str; + n_actions = 0; + for (;;) { + char *act, *arg; + size_t actlen; uint16_t port; + pos += strspn(pos, ", \t\r\n"); + if (*pos == '\0') { + break; + } + if (drop) { ovs_fatal(0, "Drop actions must not be followed by other actions"); } - /* Arguments are separated by colons */ - arg = strchr(act, ':'); - if (arg) { - *arg = '\0'; - arg++; + act = pos; + actlen = strcspn(pos, ":(, \t\r\n"); + if (act[actlen] == ':') { + /* The argument can be separated by a colon. */ + size_t arglen; + + arg = act + actlen + 1; + arglen = strcspn(arg, ", \t\r\n"); + pos = arg + arglen + (arg[arglen] != '\0'); + arg[arglen] = '\0'; + } else if (act[actlen] == '(') { + /* The argument can be surrounded by balanced parentheses. The + * outermost set of parentheses is removed. */ + int level = 1; + size_t arglen; + + arg = act + actlen + 1; + for (arglen = 0; level > 0; arglen++) { + switch (arg[arglen]) { + case '\0': + ovs_fatal(0, "unbalanced parentheses in argument to %s " + "action", act); + + case '(': + level++; + break; + + case ')': + level--; + break; + } + } + arg[arglen - 1] = '\0'; + pos = arg + arglen; + } else { + /* There might be no argument at all. */ + arg = NULL; + pos = act + actlen + (act[actlen] != '\0'); } + act[actlen] = '\0'; if (!strcasecmp(act, "mod_vlan_vid")) { struct ofp_action_vlan_vid *va; @@ -257,12 +327,22 @@ str_to_action(char *str, struct ofpbuf *b) nar->vendor = htonl(NX_VENDOR_ID); nar->subtype = htons(NXAST_RESUBMIT); nar->in_port = htons(str_to_u32(arg)); - } else if (!strcasecmp(act, "set_tunnel")) { - struct nx_action_set_tunnel *nast; - nast = put_action(b, sizeof *nast, OFPAT_VENDOR); - nast->vendor = htonl(NX_VENDOR_ID); - nast->subtype = htons(NXAST_SET_TUNNEL); - nast->tun_id = htonl(str_to_u32(arg)); + } else if (!strcasecmp(act, "set_tunnel") + || !strcasecmp(act, "set_tunnel64")) { + uint64_t tun_id = str_to_u64(arg); + if (!strcasecmp(act, "set_tunnel64") || tun_id > UINT32_MAX) { + struct nx_action_set_tunnel64 *nast64; + nast64 = put_action(b, sizeof *nast64, OFPAT_VENDOR); + nast64->vendor = htonl(NX_VENDOR_ID); + nast64->subtype = htons(NXAST_SET_TUNNEL64); + nast64->tun_id = htonll(tun_id); + } else { + struct nx_action_set_tunnel *nast; + nast = put_action(b, sizeof *nast, OFPAT_VENDOR); + nast->vendor = htonl(NX_VENDOR_ID); + nast->subtype = htons(NXAST_SET_TUNNEL); + nast->tun_id = htonl(tun_id); + } } else if (!strcasecmp(act, "drop_spoofed_arp")) { struct nx_action_header *nah; nah = put_action(b, sizeof *nah, OFPAT_VENDOR); @@ -324,6 +404,10 @@ str_to_action(char *str, struct ofpbuf *b) struct nx_action_reg_load *load; load = ofpbuf_put_uninit(b, sizeof *load); nxm_parse_reg_load(load, arg); + } else if (!strcasecmp(act, "multipath")) { + struct nx_action_multipath *nam; + nam = ofpbuf_put_uninit(b, sizeof *nam); + multipath_parse(nam, arg); } else if (!strcasecmp(act, "output")) { put_output_action(b, str_to_u32(arg)); } else if (!strcasecmp(act, "enqueue")) { @@ -360,6 +444,7 @@ str_to_action(char *str, struct ofpbuf *b) } else { ovs_fatal(0, "Unknown action: %s", act); } + n_actions++; } } @@ -392,7 +477,7 @@ parse_protocol(const char *name, const struct protocol **p_out) } #define FIELDS \ - FIELD(F_TUN_ID, "tun_id", FWW_TUN_ID) \ + FIELD(F_TUN_ID, "tun_id", 0) \ FIELD(F_IN_PORT, "in_port", FWW_IN_PORT) \ FIELD(F_DL_VLAN, "dl_vlan", 0) \ FIELD(F_DL_VLAN_PCP, "dl_vlan_pcp", 0) \ @@ -446,12 +531,14 @@ parse_field_value(struct cls_rule *rule, enum field_index index, const char *value) { uint8_t mac[ETH_ADDR_LEN]; + ovs_be64 tun_id, tun_mask; ovs_be32 ip, mask; uint16_t port_no; switch (index) { case F_TUN_ID: - cls_rule_set_tun_id(rule, htonl(str_to_u32(value))); + str_to_tun_id(value, &tun_id, &tun_mask); + cls_rule_set_tun_id_masked(rule, tun_id, tun_mask); break; case F_IN_PORT: