1 /* Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
20 #include <arpa/inet.h>
23 #include "dynamic-string.h"
24 #include "multipath.h"
25 #include "meta-flow.h"
28 #include "ofp-actions.h"
29 #include "ofp-errors.h"
31 #include "openflow/nicira-ext.h"
32 #include "openvswitch/vlog.h"
34 VLOG_DEFINE_THIS_MODULE(bundle
);
37 execute_ab(const struct ofpact_bundle
*bundle
,
38 bool (*slave_enabled
)(ofp_port_t ofp_port
, void *aux
), void *aux
)
42 for (i
= 0; i
< bundle
->n_slaves
; i
++) {
43 ofp_port_t slave
= bundle
->slaves
[i
];
44 if (slave_enabled(slave
, aux
)) {
53 execute_hrw(const struct ofpact_bundle
*bundle
,
54 const struct flow
*flow
, struct flow_wildcards
*wc
,
55 bool (*slave_enabled
)(ofp_port_t ofp_port
, void *aux
), void *aux
)
57 uint32_t flow_hash
, best_hash
;
60 if (bundle
->n_slaves
> 1) {
61 flow_mask_hash_fields(flow
, wc
, bundle
->fields
);
64 flow_hash
= flow_hash_fields(flow
, bundle
->fields
, bundle
->basis
);
68 for (i
= 0; i
< bundle
->n_slaves
; i
++) {
69 if (slave_enabled(bundle
->slaves
[i
], aux
)) {
70 uint32_t hash
= hash_2words(i
, flow_hash
);
72 if (best
< 0 || hash
> best_hash
) {
79 return best
>= 0 ? bundle
->slaves
[best
] : OFPP_NONE
;
82 /* Executes 'bundle' on 'flow'. Sets fields in 'wc' that were used to
83 * calculate the result. Uses 'slave_enabled' to determine if the slave
84 * designated by 'ofp_port' is up. Returns the chosen slave, or
85 * OFPP_NONE if none of the slaves are acceptable. */
87 bundle_execute(const struct ofpact_bundle
*bundle
,
88 const struct flow
*flow
, struct flow_wildcards
*wc
,
89 bool (*slave_enabled
)(ofp_port_t ofp_port
, void *aux
),
92 switch (bundle
->algorithm
) {
94 return execute_hrw(bundle
, flow
, wc
, slave_enabled
, aux
);
96 case NX_BD_ALG_ACTIVE_BACKUP
:
97 return execute_ab(bundle
, slave_enabled
, aux
);
105 bundle_check(const struct ofpact_bundle
*bundle
, ofp_port_t max_ports
,
106 const struct flow
*flow
)
108 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
111 if (bundle
->dst
.field
) {
112 enum ofperr error
= mf_check_dst(&bundle
->dst
, flow
);
118 for (i
= 0; i
< bundle
->n_slaves
; i
++) {
119 ofp_port_t ofp_port
= bundle
->slaves
[i
];
122 error
= ofpact_check_output_port(ofp_port
, max_ports
);
124 VLOG_WARN_RL(&rl
, "invalid slave %"PRIu16
, ofp_port
);
128 /* Controller slaves are unsupported due to the lack of a max_len
129 * argument. This may or may not change in the future. There doesn't
130 * seem to be a real-world use-case for supporting it. */
131 if (ofp_port
== OFPP_CONTROLLER
) {
132 VLOG_WARN_RL(&rl
, "unsupported controller slave");
133 return OFPERR_OFPBAC_BAD_OUT_PORT
;
141 /* Helper for bundle_parse and bundle_parse_load.
143 * Returns NULL if successful, otherwise a malloc()'d string describing the
144 * error. The caller is responsible for freeing the returned string.*/
145 static char * OVS_WARN_UNUSED_RESULT
146 bundle_parse__(const char *s
, char **save_ptr
,
147 const char *fields
, const char *basis
, const char *algorithm
,
148 const char *slave_type
, const char *dst
,
149 const char *slave_delim
, struct ofpbuf
*ofpacts
)
151 struct ofpact_bundle
*bundle
;
154 return xasprintf("%s: not enough arguments to bundle action", s
);
157 if (strcasecmp(slave_delim
, "slaves")) {
158 return xasprintf("%s: missing slave delimiter, expected `slaves' "
159 "got `%s'", s
, slave_delim
);
162 bundle
= ofpact_put_BUNDLE(ofpacts
);
165 ofp_port_t slave_port
;
168 slave
= strtok_r(NULL
, ", []", save_ptr
);
169 if (!slave
|| bundle
->n_slaves
>= BUNDLE_MAX_SLAVES
) {
173 if (!ofputil_port_from_string(slave
, &slave_port
)) {
174 return xasprintf("%s: bad port number", slave
);
176 ofpbuf_put(ofpacts
, &slave_port
, sizeof slave_port
);
178 bundle
= ofpacts
->header
;
181 ofpact_update_len(ofpacts
, &bundle
->ofpact
);
183 bundle
->basis
= atoi(basis
);
185 if (!strcasecmp(fields
, "eth_src")) {
186 bundle
->fields
= NX_HASH_FIELDS_ETH_SRC
;
187 } else if (!strcasecmp(fields
, "symmetric_l4")) {
188 bundle
->fields
= NX_HASH_FIELDS_SYMMETRIC_L4
;
190 return xasprintf("%s: unknown fields `%s'", s
, fields
);
193 if (!strcasecmp(algorithm
, "active_backup")) {
194 bundle
->algorithm
= NX_BD_ALG_ACTIVE_BACKUP
;
195 } else if (!strcasecmp(algorithm
, "hrw")) {
196 bundle
->algorithm
= NX_BD_ALG_HRW
;
198 return xasprintf("%s: unknown algorithm `%s'", s
, algorithm
);
201 if (strcasecmp(slave_type
, "ofport")) {
202 return xasprintf("%s: unknown slave_type `%s'", s
, slave_type
);
206 char *error
= mf_parse_subfield(&bundle
->dst
, dst
);
211 if (!mf_nxm_header(bundle
->dst
.field
->id
)) {
212 return xasprintf("%s: experimenter OXM field '%s' not supported",
220 /* Converts a bundle action string contained in 's' to an nx_action_bundle and
221 * stores it in 'b'. Sets 'b''s l2 pointer to NULL.
223 * Returns NULL if successful, otherwise a malloc()'d string describing the
224 * error. The caller is responsible for freeing the returned string. */
225 char * OVS_WARN_UNUSED_RESULT
226 bundle_parse(const char *s
, struct ofpbuf
*ofpacts
)
228 char *fields
, *basis
, *algorithm
, *slave_type
, *slave_delim
;
229 char *tokstr
, *save_ptr
;
234 fields
= strtok_r(tokstr
, ", ", &save_ptr
);
235 basis
= strtok_r(NULL
, ", ", &save_ptr
);
236 algorithm
= strtok_r(NULL
, ", ", &save_ptr
);
237 slave_type
= strtok_r(NULL
, ", ", &save_ptr
);
238 slave_delim
= strtok_r(NULL
, ": ", &save_ptr
);
240 error
= bundle_parse__(s
, &save_ptr
, fields
, basis
, algorithm
, slave_type
,
241 NULL
, slave_delim
, ofpacts
);
247 /* Converts a bundle_load action string contained in 's' to an nx_action_bundle
248 * and stores it in 'b'. Sets 'b''s l2 pointer to NULL.
250 * Returns NULL if successful, otherwise a malloc()'d string describing the
251 * error. The caller is responsible for freeing the returned string.*/
252 char * OVS_WARN_UNUSED_RESULT
253 bundle_parse_load(const char *s
, struct ofpbuf
*ofpacts
)
255 char *fields
, *basis
, *algorithm
, *slave_type
, *dst
, *slave_delim
;
256 char *tokstr
, *save_ptr
;
261 fields
= strtok_r(tokstr
, ", ", &save_ptr
);
262 basis
= strtok_r(NULL
, ", ", &save_ptr
);
263 algorithm
= strtok_r(NULL
, ", ", &save_ptr
);
264 slave_type
= strtok_r(NULL
, ", ", &save_ptr
);
265 dst
= strtok_r(NULL
, ", ", &save_ptr
);
266 slave_delim
= strtok_r(NULL
, ": ", &save_ptr
);
268 error
= bundle_parse__(s
, &save_ptr
, fields
, basis
, algorithm
, slave_type
,
269 dst
, slave_delim
, ofpacts
);
276 /* Appends a human-readable representation of 'nab' to 's'. */
278 bundle_format(const struct ofpact_bundle
*bundle
, struct ds
*s
)
280 const char *action
, *fields
, *algorithm
;
283 fields
= flow_hash_fields_to_str(bundle
->fields
);
285 switch (bundle
->algorithm
) {
289 case NX_BD_ALG_ACTIVE_BACKUP
:
290 algorithm
= "active_backup";
293 algorithm
= "<unknown>";
296 action
= bundle
->dst
.field
? "bundle_load" : "bundle";
298 ds_put_format(s
, "%s(%s,%"PRIu16
",%s,%s,", action
, fields
,
299 bundle
->basis
, algorithm
, "ofport");
301 if (bundle
->dst
.field
) {
302 mf_format_subfield(&bundle
->dst
, s
);
306 ds_put_cstr(s
, "slaves:");
307 for (i
= 0; i
< bundle
->n_slaves
; i
++) {
312 ofputil_format_port(bundle
->slaves
[i
], s
);