1 /* Copyright (c) 2011, 2012 Nicira Networks.
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"
27 #include "ofp-errors.h"
29 #include "openflow/nicira-ext.h"
32 #define BUNDLE_MAX_SLAVES 2048
34 VLOG_DEFINE_THIS_MODULE(bundle
);
37 execute_ab(const struct nx_action_bundle
*nab
,
38 bool (*slave_enabled
)(uint16_t ofp_port
, void *aux
), void *aux
)
42 for (i
= 0; i
< ntohs(nab
->n_slaves
); i
++) {
43 uint16_t slave
= bundle_get_slave(nab
, i
);
45 if (slave_enabled(slave
, aux
)) {
54 execute_hrw(const struct nx_action_bundle
*nab
, const struct flow
*flow
,
55 bool (*slave_enabled
)(uint16_t ofp_port
, void *aux
), void *aux
)
57 uint32_t flow_hash
, best_hash
;
60 flow_hash
= flow_hash_fields(flow
, ntohs(nab
->fields
), ntohs(nab
->basis
));
64 for (i
= 0; i
< ntohs(nab
->n_slaves
); i
++) {
65 if (slave_enabled(bundle_get_slave(nab
, i
), aux
)) {
66 uint32_t hash
= hash_2words(i
, flow_hash
);
68 if (best
< 0 || hash
> best_hash
) {
75 return best
>= 0 ? bundle_get_slave(nab
, best
) : OFPP_NONE
;
78 /* Executes 'nab' on 'flow'. Uses 'slave_enabled' to determine if the slave
79 * designated by 'ofp_port' is up. Returns the chosen slave, or OFPP_NONE if
80 * none of the slaves are acceptable. */
82 bundle_execute(const struct nx_action_bundle
*nab
, const struct flow
*flow
,
83 bool (*slave_enabled
)(uint16_t ofp_port
, void *aux
), void *aux
)
85 switch (ntohs(nab
->algorithm
)) {
86 case NX_BD_ALG_HRW
: return execute_hrw(nab
, flow
, slave_enabled
, aux
);
87 case NX_BD_ALG_ACTIVE_BACKUP
: return execute_ab(nab
, slave_enabled
, aux
);
88 default: NOT_REACHED();
93 bundle_execute_load(const struct nx_action_bundle
*nab
, struct flow
*flow
,
94 bool (*slave_enabled
)(uint16_t ofp_port
, void *aux
),
97 nxm_reg_load(nab
->dst
, nab
->ofs_nbits
,
98 bundle_execute(nab
, flow
, slave_enabled
, aux
), flow
);
101 /* Checks that 'nab' specifies a bundle action which is supported by this
102 * bundle module. Uses the 'max_ports' parameter to validate each port using
103 * ofputil_check_output_port(). Returns 0 if 'nab' is supported, otherwise an
104 * OFPERR_* error code. */
106 bundle_check(const struct nx_action_bundle
*nab
, int max_ports
,
107 const struct flow
*flow
)
109 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 5);
110 uint16_t n_slaves
, fields
, algorithm
, subtype
;
112 size_t slaves_size
, i
;
115 subtype
= ntohs(nab
->subtype
);
116 n_slaves
= ntohs(nab
->n_slaves
);
117 fields
= ntohs(nab
->fields
);
118 algorithm
= ntohs(nab
->algorithm
);
119 slave_type
= ntohl(nab
->slave_type
);
120 slaves_size
= ntohs(nab
->len
) - sizeof *nab
;
122 error
= OFPERR_OFPBAC_BAD_ARGUMENT
;
123 if (!flow_hash_fields_valid(fields
)) {
124 VLOG_WARN_RL(&rl
, "unsupported fields %"PRIu16
, fields
);
125 } else if (n_slaves
> BUNDLE_MAX_SLAVES
) {
126 VLOG_WARN_RL(&rl
, "too may slaves");
127 } else if (algorithm
!= NX_BD_ALG_HRW
128 && algorithm
!= NX_BD_ALG_ACTIVE_BACKUP
) {
129 VLOG_WARN_RL(&rl
, "unsupported algorithm %"PRIu16
, algorithm
);
130 } else if (slave_type
!= NXM_OF_IN_PORT
) {
131 VLOG_WARN_RL(&rl
, "unsupported slave type %"PRIu16
, slave_type
);
136 for (i
= 0; i
< sizeof(nab
->zero
); i
++) {
138 VLOG_WARN_RL(&rl
, "reserved field is nonzero");
139 error
= OFPERR_OFPBAC_BAD_ARGUMENT
;
143 if (subtype
== NXAST_BUNDLE
&& (nab
->ofs_nbits
|| nab
->dst
)) {
144 VLOG_WARN_RL(&rl
, "bundle action has nonzero reserved fields");
145 error
= OFPERR_OFPBAC_BAD_ARGUMENT
;
148 if (subtype
== NXAST_BUNDLE_LOAD
) {
149 int ofs
= nxm_decode_ofs(nab
->ofs_nbits
);
150 int n_bits
= nxm_decode_n_bits(nab
->ofs_nbits
);
153 VLOG_WARN_RL(&rl
, "bundle_load action requires at least 16 bit "
155 error
= OFPERR_OFPBAC_BAD_ARGUMENT
;
157 error
= nxm_dst_check(nab
->dst
, ofs
, n_bits
, flow
);
161 if (slaves_size
< n_slaves
* sizeof(ovs_be16
)) {
162 VLOG_WARN_RL(&rl
, "Nicira action %"PRIu16
" only has %zu bytes "
163 "allocated for slaves. %zu bytes are required for "
164 "%"PRIu16
" slaves.", subtype
, slaves_size
,
165 n_slaves
* sizeof(ovs_be16
), n_slaves
);
166 error
= OFPERR_OFPBAC_BAD_LEN
;
169 for (i
= 0; i
< n_slaves
; i
++) {
170 uint16_t ofp_port
= bundle_get_slave(nab
, i
);
171 enum ofperr ofputil_error
;
173 ofputil_error
= ofputil_check_output_port(ofp_port
, max_ports
);
175 VLOG_WARN_RL(&rl
, "invalid slave %"PRIu16
, ofp_port
);
176 error
= ofputil_error
;
179 /* Controller slaves are unsupported due to the lack of a max_len
180 * argument. This may or may not change in the future. There doesn't
181 * seem to be a real-world use-case for supporting it. */
182 if (ofp_port
== OFPP_CONTROLLER
) {
183 VLOG_WARN_RL(&rl
, "unsupported controller slave");
184 error
= OFPERR_OFPBAC_BAD_OUT_PORT
;
191 /* Helper for bundle_parse and bundle_parse_load. */
193 bundle_parse__(struct ofpbuf
*b
, const char *s
, char **save_ptr
,
194 const char *fields
, const char *basis
, const char *algorithm
,
195 const char *slave_type
, const char *dst
,
196 const char *slave_delim
)
198 enum ofputil_action_code code
;
199 struct nx_action_bundle
*nab
;
203 ovs_fatal(0, "%s: not enough arguments to bundle action", s
);
206 if (strcasecmp(slave_delim
, "slaves")) {
207 ovs_fatal(0, "%s: missing slave delimiter, expected `slaves' got `%s'",
211 code
= dst
? OFPUTIL_NXAST_BUNDLE_LOAD
: OFPUTIL_NXAST_BUNDLE
;
212 b
->l2
= ofputil_put_action(code
, b
);
219 slave
= strtok_r(NULL
, ", [", save_ptr
);
220 if (!slave
|| n_slaves
>= BUNDLE_MAX_SLAVES
) {
224 slave_be
= htons(atoi(slave
));
225 ofpbuf_put(b
, &slave_be
, sizeof slave_be
);
230 /* Slaves array must be multiple of 8 bytes long. */
232 ofpbuf_put_zeros(b
, 8 - (b
->size
% 8));
236 nab
->len
= htons(b
->size
- ((char *) b
->l2
- (char *) b
->data
));
237 nab
->n_slaves
= htons(n_slaves
);
238 nab
->basis
= htons(atoi(basis
));
240 if (!strcasecmp(fields
, "eth_src")) {
241 nab
->fields
= htons(NX_HASH_FIELDS_ETH_SRC
);
242 } else if (!strcasecmp(fields
, "symmetric_l4")) {
243 nab
->fields
= htons(NX_HASH_FIELDS_SYMMETRIC_L4
);
245 ovs_fatal(0, "%s: unknown fields `%s'", s
, fields
);
248 if (!strcasecmp(algorithm
, "active_backup")) {
249 nab
->algorithm
= htons(NX_BD_ALG_ACTIVE_BACKUP
);
250 } else if (!strcasecmp(algorithm
, "hrw")) {
251 nab
->algorithm
= htons(NX_BD_ALG_HRW
);
253 ovs_fatal(0, "%s: unknown algorithm `%s'", s
, algorithm
);
256 if (!strcasecmp(slave_type
, "ofport")) {
257 nab
->slave_type
= htonl(NXM_OF_IN_PORT
);
259 ovs_fatal(0, "%s: unknown slave_type `%s'", s
, slave_type
);
266 nxm_parse_field_bits(dst
, ®
, &ofs
, &n_bits
);
268 nab
->dst
= htonl(reg
);
269 nab
->ofs_nbits
= nxm_encode_ofs_nbits(ofs
, n_bits
);
275 /* Converts a bundle action string contained in 's' to an nx_action_bundle and
276 * stores it in 'b'. Sets 'b''s l2 pointer to NULL. */
278 bundle_parse(struct ofpbuf
*b
, const char *s
)
280 char *fields
, *basis
, *algorithm
, *slave_type
, *slave_delim
;
281 char *tokstr
, *save_ptr
;
285 fields
= strtok_r(tokstr
, ", ", &save_ptr
);
286 basis
= strtok_r(NULL
, ", ", &save_ptr
);
287 algorithm
= strtok_r(NULL
, ", ", &save_ptr
);
288 slave_type
= strtok_r(NULL
, ", ", &save_ptr
);
289 slave_delim
= strtok_r(NULL
, ": ", &save_ptr
);
291 bundle_parse__(b
, s
, &save_ptr
, fields
, basis
, algorithm
, slave_type
, NULL
,
296 /* Converts a bundle_load action string contained in 's' to an nx_action_bundle
297 * and stores it in 'b'. Sets 'b''s l2 pointer to NULL. */
299 bundle_parse_load(struct ofpbuf
*b
, const char *s
)
301 char *fields
, *basis
, *algorithm
, *slave_type
, *dst
, *slave_delim
;
302 char *tokstr
, *save_ptr
;
306 fields
= strtok_r(tokstr
, ", ", &save_ptr
);
307 basis
= strtok_r(NULL
, ", ", &save_ptr
);
308 algorithm
= strtok_r(NULL
, ", ", &save_ptr
);
309 slave_type
= strtok_r(NULL
, ", ", &save_ptr
);
310 dst
= strtok_r(NULL
, ", ", &save_ptr
);
311 slave_delim
= strtok_r(NULL
, ": ", &save_ptr
);
313 bundle_parse__(b
, s
, &save_ptr
, fields
, basis
, algorithm
, slave_type
, dst
,
319 /* Appends a human-readable representation of 'nab' to 's'. */
321 bundle_format(const struct nx_action_bundle
*nab
, struct ds
*s
)
323 const char *action
, *fields
, *algorithm
, *slave_type
;
326 fields
= flow_hash_fields_to_str(ntohs(nab
->fields
));
328 switch (ntohs(nab
->algorithm
)) {
332 case NX_BD_ALG_ACTIVE_BACKUP
:
333 algorithm
= "active_backup";
336 algorithm
= "<unknown>";
339 switch (ntohl(nab
->slave_type
)) {
341 slave_type
= "ofport";
344 slave_type
= "<unknown>";
347 switch (ntohs(nab
->subtype
)) {
351 case NXAST_BUNDLE_LOAD
:
352 action
= "bundle_load";
358 ds_put_format(s
, "%s(%s,%"PRIu16
",%s,%s,", action
, fields
,
359 ntohs(nab
->basis
), algorithm
, slave_type
);
361 if (nab
->subtype
== htons(NXAST_BUNDLE_LOAD
)) {
362 nxm_format_field_bits(s
, ntohl(nab
->dst
),
363 nxm_decode_ofs(nab
->ofs_nbits
),
364 nxm_decode_n_bits(nab
->ofs_nbits
));
368 ds_put_cstr(s
, "slaves:");
369 for (i
= 0; i
< ntohs(nab
->n_slaves
); i
++) {
374 ds_put_format(s
, "%"PRIu16
, bundle_get_slave(nab
, i
));