]>
git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-parse.c
2 * Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "openvswitch/ofp-parse.h"
20 #include "byte-order.h"
21 #include "openvswitch/match.h"
22 #include "openvswitch/meta-flow.h"
23 #include "openvswitch/ofp-actions.h"
24 #include "openvswitch/ofp-flow.h"
25 #include "openvswitch/ofp-match.h"
26 #include "openvswitch/ofp-table.h"
28 #include "socket-util.h"
31 /* Parses 'str' as an 8-bit unsigned integer into '*valuep'.
33 * 'name' describes the value parsed in an error message, if any.
35 * Returns NULL if successful, otherwise a malloc()'d string describing the
36 * error. The caller is responsible for freeing the returned string. */
37 char * OVS_WARN_UNUSED_RESULT
38 str_to_u8(const char *str
, const char *name
, uint8_t *valuep
)
42 if (!str_to_int(str
, 0, &value
) || value
< 0 || value
> 255) {
43 return xasprintf("invalid %s \"%s\"", name
, str
);
49 /* Parses 'str' as a 16-bit unsigned integer into '*valuep'.
51 * 'name' describes the value parsed in an error message, if any.
53 * Returns NULL if successful, otherwise a malloc()'d string describing the
54 * error. The caller is responsible for freeing the returned string. */
55 char * OVS_WARN_UNUSED_RESULT
56 str_to_u16(const char *str
, const char *name
, uint16_t *valuep
)
60 if (!str_to_int(str
, 0, &value
) || value
< 0 || value
> 65535) {
61 return xasprintf("invalid %s \"%s\"", name
, str
);
67 /* Parses 'str' as a 32-bit unsigned integer into '*valuep'.
69 * Returns NULL if successful, otherwise a malloc()'d string describing the
70 * error. The caller is responsible for freeing the returned string. */
71 char * OVS_WARN_UNUSED_RESULT
72 str_to_u32(const char *str
, uint32_t *valuep
)
78 return xstrdup("missing required numeric argument");
82 value
= strtoul(str
, &tail
, 0);
83 if (errno
== EINVAL
|| errno
== ERANGE
|| *tail
) {
84 return xasprintf("invalid numeric format %s", str
);
90 /* Parses 'str' as an 64-bit unsigned integer into '*valuep'.
92 * Returns NULL if successful, otherwise a malloc()'d string describing the
93 * error. The caller is responsible for freeing the returned string. */
94 char * OVS_WARN_UNUSED_RESULT
95 str_to_u64(const char *str
, uint64_t *valuep
)
101 return xstrdup("missing required numeric argument");
105 value
= strtoull(str
, &tail
, 0);
106 if (errno
== EINVAL
|| errno
== ERANGE
|| *tail
) {
107 return xasprintf("invalid numeric format %s", str
);
113 /* Parses 'str' as an 64-bit unsigned integer in network byte order into
116 * Returns NULL if successful, otherwise a malloc()'d string describing the
117 * error. The caller is responsible for freeing the returned string. */
118 char * OVS_WARN_UNUSED_RESULT
119 str_to_be64(const char *str
, ovs_be64
*valuep
)
124 error
= str_to_u64(str
, &value
);
126 *valuep
= htonll(value
);
131 /* Parses 'str' as an Ethernet address into 'mac'.
133 * Returns NULL if successful, otherwise a malloc()'d string describing the
134 * error. The caller is responsible for freeing the returned string. */
135 char * OVS_WARN_UNUSED_RESULT
136 str_to_mac(const char *str
, struct eth_addr
*mac
)
138 if (!ovs_scan(str
, ETH_ADDR_SCAN_FMT
, ETH_ADDR_SCAN_ARGS(*mac
))) {
139 return xasprintf("invalid mac address %s", str
);
144 /* Parses 'str' as an IP address into '*ip'.
146 * Returns NULL if successful, otherwise a malloc()'d string describing the
147 * error. The caller is responsible for freeing the returned string. */
148 char * OVS_WARN_UNUSED_RESULT
149 str_to_ip(const char *str
, ovs_be32
*ip
)
151 struct in_addr in_addr
;
153 if (lookup_ip(str
, &in_addr
)) {
154 return xasprintf("%s: could not convert to IP address", str
);
156 *ip
= in_addr
.s_addr
;
160 /* Parses 'str' as a conntrack helper into 'alg'.
162 * Returns NULL if successful, otherwise a malloc()'d string describing the
163 * error. The caller is responsible for freeing the returned string. */
164 char * OVS_WARN_UNUSED_RESULT
165 str_to_connhelper(const char *str
, uint16_t *alg
)
167 if (!strcmp(str
, "ftp")) {
171 if (!strcmp(str
, "tftp")) {
175 return xasprintf("invalid conntrack helper \"%s\"", str
);
179 ofp_parse_protocol(const char *name
, const struct ofp_protocol
**p_out
)
181 static const struct ofp_protocol protocols
[] = {
182 { "ip", ETH_TYPE_IP
, 0 },
183 { "ipv4", ETH_TYPE_IP
, 0 },
184 { "ip4", ETH_TYPE_IP
, 0 },
185 { "arp", ETH_TYPE_ARP
, 0 },
186 { "icmp", ETH_TYPE_IP
, IPPROTO_ICMP
},
187 { "tcp", ETH_TYPE_IP
, IPPROTO_TCP
},
188 { "udp", ETH_TYPE_IP
, IPPROTO_UDP
},
189 { "sctp", ETH_TYPE_IP
, IPPROTO_SCTP
},
190 { "ipv6", ETH_TYPE_IPV6
, 0 },
191 { "ip6", ETH_TYPE_IPV6
, 0 },
192 { "icmp6", ETH_TYPE_IPV6
, IPPROTO_ICMPV6
},
193 { "tcp6", ETH_TYPE_IPV6
, IPPROTO_TCP
},
194 { "udp6", ETH_TYPE_IPV6
, IPPROTO_UDP
},
195 { "sctp6", ETH_TYPE_IPV6
, IPPROTO_SCTP
},
196 { "rarp", ETH_TYPE_RARP
, 0},
197 { "mpls", ETH_TYPE_MPLS
, 0 },
198 { "mplsm", ETH_TYPE_MPLS_MCAST
, 0 },
200 const struct ofp_protocol
*p
;
202 for (p
= protocols
; p
< &protocols
[ARRAY_SIZE(protocols
)]; p
++) {
203 if (!strcmp(p
->name
, name
)) {
212 /* Parses 's' as the (possibly masked) value of field 'mf', and updates
213 * 'match' appropriately. Restricts the set of usable protocols to ones
214 * supporting the parsed field.
216 * Returns NULL if successful, otherwise a malloc()'d string describing the
217 * error. The caller is responsible for freeing the returned string. */
218 char * OVS_WARN_UNUSED_RESULT
219 ofp_parse_field(const struct mf_field
*mf
, const char *s
,
220 const struct ofputil_port_map
*port_map
, struct match
*match
,
221 enum ofputil_protocol
*usable_protocols
)
223 union mf_value value
, mask
;
227 /* If there's no string, we're just trying to match on the
228 * existence of the field, so use a no-op value. */
232 error
= mf_parse(mf
, s
, port_map
, &value
, &mask
);
234 *usable_protocols
&= mf_set(mf
, &value
, &mask
, match
, &error
);
235 match_add_ethernet_prereq(match
, mf
);
241 ofp_extract_actions(char *s
)
243 s
= strstr(s
, "action");
246 s
= strchr(s
+ 1, '=');
247 return s
? s
+ 1 : NULL
;
254 parse_value(const char *s
, const char *delimiters
)
258 /* Iterate until we reach a delimiter.
260 * strchr(s, '\0') returns s+strlen(s), so this test handles the null
261 * terminator at the end of 's'. */
262 while (!strchr(delimiters
, s
[n
])) {
285 /* Parses a key or a key-value pair from '*stringp'.
287 * On success: Stores the key into '*keyp'. Stores the value, if present, into
288 * '*valuep', otherwise an empty string. Advances '*stringp' past the end of
289 * the key-value pair, preparing it for another call. '*keyp' and '*valuep'
290 * are substrings of '*stringp' created by replacing some of its bytes by null
291 * terminators. Returns true.
293 * If '*stringp' is just white space or commas, sets '*keyp' and '*valuep' to
294 * NULL and returns false. */
296 ofputil_parse_key_value(char **stringp
, char **keyp
, char **valuep
)
298 /* Skip white space and delimiters. If that brings us to the end of the
299 * input string, we are done and there are no more key-value pairs. */
300 *stringp
+= strspn(*stringp
, ", \t\r\n");
301 if (**stringp
== '\0') {
302 *keyp
= *valuep
= NULL
;
306 /* Extract the key and the delimiter that ends the key-value pair or begins
307 * the value. Advance the input position past the key and delimiter. */
308 char *key
= *stringp
;
309 size_t key_len
= strcspn(key
, ":=(, \t\r\n");
310 char key_delim
= key
[key_len
];
312 *stringp
+= key_len
+ (key_delim
!= '\0');
314 /* Figure out what delimiter ends the value:
316 * - If key_delim is ":" or "=", the value extends until white space
319 * - If key_delim is "(", the value extends until ")".
321 * If there is no value, we are done. */
322 const char *value_delims
;
323 if (key_delim
== ':' || key_delim
== '=') {
324 value_delims
= ", \t\r\n";
325 } else if (key_delim
== '(') {
329 *valuep
= key
+ key_len
; /* Empty string. */
333 /* Extract the value. Advance the input position past the value and
335 char *value
= *stringp
;
336 size_t value_len
= parse_value(value
, value_delims
);
337 char value_delim
= value
[value_len
];
339 /* Handle the special case if the value is of the form "(x)->y".
340 * After parsing, 'valuep' will be pointing to - "x)->y".
342 if (key_delim
== '(' && value
[value_len
] == ')' &&
343 value
[value_len
+ 1] == '-' && value
[value_len
+ 2] == '>') {
344 value_delims
= ", \t\r\n";
345 value_len
+= parse_value(&value
[value_len
], value_delims
);
346 value_delim
= value
[value_len
];
348 value
[value_len
] = '\0';
349 *stringp
+= value_len
+ (value_delim
!= '\0');