]> git.proxmox.com Git - mirror_ovs.git/blob - lib/learning-switch.c
mac-learning: Implement per-port MAC learning fairness.
[mirror_ovs.git] / lib / learning-switch.c
1 /*
2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
3 *
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:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 #include <config.h>
18 #include "learning-switch.h"
19
20 #include <errno.h>
21 #include <inttypes.h>
22 #include <netinet/in.h>
23 #include <stdlib.h>
24 #include <time.h>
25
26 #include "byte-order.h"
27 #include "classifier.h"
28 #include "flow.h"
29 #include "hmap.h"
30 #include "mac-learning.h"
31 #include "ofpbuf.h"
32 #include "ofp-actions.h"
33 #include "ofp-errors.h"
34 #include "ofp-msgs.h"
35 #include "ofp-parse.h"
36 #include "ofp-print.h"
37 #include "ofp-util.h"
38 #include "openflow/openflow.h"
39 #include "poll-loop.h"
40 #include "rconn.h"
41 #include "shash.h"
42 #include "simap.h"
43 #include "timeval.h"
44 #include "openvswitch/vconn.h"
45 #include "openvswitch/vlog.h"
46
47 VLOG_DEFINE_THIS_MODULE(learning_switch);
48
49 struct lswitch_port {
50 struct hmap_node hmap_node; /* Hash node for port number. */
51 ofp_port_t port_no; /* OpenFlow port number. */
52 uint32_t queue_id; /* OpenFlow queue number. */
53 };
54
55 enum lswitch_state {
56 S_CONNECTING, /* Waiting for connection to complete. */
57 S_FEATURES_REPLY, /* Waiting for features reply. */
58 S_SWITCHING, /* Switching flows. */
59 };
60
61 struct lswitch {
62 struct rconn *rconn;
63 enum lswitch_state state;
64
65 /* If nonnegative, the switch sets up flows that expire after the given
66 * number of seconds (or never expire, if the value is OFP_FLOW_PERMANENT).
67 * Otherwise, the switch processes every packet. */
68 int max_idle;
69
70 enum ofputil_protocol protocol;
71 unsigned long long int datapath_id;
72 struct mac_learning *ml; /* NULL to act as hub instead of switch. */
73 struct flow_wildcards wc; /* Wildcards to apply to flows. */
74 bool action_normal; /* Use OFPP_NORMAL? */
75
76 /* Queue distribution. */
77 uint32_t default_queue; /* Default OpenFlow queue, or UINT32_MAX. */
78 struct hmap queue_numbers; /* Map from port number to lswitch_port. */
79 struct shash queue_names; /* Map from port name to lswitch_port. */
80
81 /* Number of outgoing queued packets on the rconn. */
82 struct rconn_packet_counter *queued;
83
84 /* If true, do not reply to any messages from the switch (for debugging
85 * fail-open mode). */
86 bool mute;
87
88 /* Optional "flow mod" requests to send to the switch at connection time,
89 * to set up the flow table. */
90 const struct ofputil_flow_mod *default_flows;
91 size_t n_default_flows;
92 enum ofputil_protocol usable_protocols;
93 };
94
95 /* The log messages here could actually be useful in debugging, so keep the
96 * rate limit relatively high. */
97 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300);
98
99 static void queue_tx(struct lswitch *, struct ofpbuf *);
100 static void send_features_request(struct lswitch *);
101
102 static void lswitch_process_packet(struct lswitch *, const struct ofpbuf *);
103 static enum ofperr process_switch_features(struct lswitch *,
104 struct ofp_header *);
105 static void process_packet_in(struct lswitch *, const struct ofp_header *);
106 static void process_echo_request(struct lswitch *, const struct ofp_header *);
107
108 static ofp_port_t get_mac_entry_ofp_port(const struct mac_learning *ml,
109 const struct mac_entry *)
110 OVS_REQ_RDLOCK(ml->rwlock);
111 static void set_mac_entry_ofp_port(struct mac_learning *ml,
112 struct mac_entry *, ofp_port_t)
113 OVS_REQ_WRLOCK(ml->rwlock);
114
115 /* Creates and returns a new learning switch whose configuration is given by
116 * 'cfg'.
117 *
118 * 'rconn' is used to send out an OpenFlow features request. */
119 struct lswitch *
120 lswitch_create(struct rconn *rconn, const struct lswitch_config *cfg)
121 {
122 struct lswitch *sw;
123 uint32_t ofpfw;
124
125 sw = xzalloc(sizeof *sw);
126 sw->rconn = rconn;
127 sw->state = S_CONNECTING;
128 sw->max_idle = cfg->max_idle;
129 sw->datapath_id = 0;
130 sw->ml = (cfg->mode == LSW_LEARN
131 ? mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME)
132 : NULL);
133 sw->action_normal = cfg->mode == LSW_NORMAL;
134
135 switch (cfg->wildcards) {
136 case 0:
137 ofpfw = 0;
138 break;
139
140 case UINT32_MAX:
141 /* Try to wildcard as many fields as possible, but we cannot
142 * wildcard all fields. We need in_port to detect moves. We need
143 * Ethernet source and dest and VLAN VID to do L2 learning. */
144 ofpfw = (OFPFW10_DL_TYPE | OFPFW10_DL_VLAN_PCP
145 | OFPFW10_NW_SRC_ALL | OFPFW10_NW_DST_ALL
146 | OFPFW10_NW_TOS | OFPFW10_NW_PROTO
147 | OFPFW10_TP_SRC | OFPFW10_TP_DST);
148 break;
149
150 default:
151 ofpfw = cfg->wildcards;
152 break;
153 }
154 ofputil_wildcard_from_ofpfw10(ofpfw, &sw->wc);
155
156 sw->default_queue = cfg->default_queue;
157 hmap_init(&sw->queue_numbers);
158 shash_init(&sw->queue_names);
159 if (cfg->port_queues) {
160 struct simap_node *node;
161
162 SIMAP_FOR_EACH (node, cfg->port_queues) {
163 struct lswitch_port *port = xmalloc(sizeof *port);
164 hmap_node_nullify(&port->hmap_node);
165 port->queue_id = node->data;
166 shash_add(&sw->queue_names, node->name, port);
167 }
168 }
169
170 sw->default_flows = cfg->default_flows;
171 sw->n_default_flows = cfg->n_default_flows;
172 sw->usable_protocols = cfg->usable_protocols;
173
174 sw->queued = rconn_packet_counter_create();
175
176 return sw;
177 }
178
179 static void
180 lswitch_handshake(struct lswitch *sw)
181 {
182 enum ofputil_protocol protocol;
183 enum ofp_version version;
184
185 send_features_request(sw);
186
187 version = rconn_get_version(sw->rconn);
188 protocol = ofputil_protocol_from_ofp_version(version);
189 if (version >= OFP13_VERSION) {
190 /* OpenFlow 1.3 and later by default drop packets that miss in the flow
191 * table. Set up a flow to send packets to the controller by
192 * default. */
193 struct ofputil_flow_mod fm;
194 struct ofpact_output output;
195 struct ofpbuf *msg;
196 int error;
197
198 ofpact_init_OUTPUT(&output);
199 output.port = OFPP_CONTROLLER;
200 output.max_len = OFP_DEFAULT_MISS_SEND_LEN;
201
202 match_init_catchall(&fm.match);
203 fm.priority = 0;
204 fm.cookie = 0;
205 fm.cookie_mask = 0;
206 fm.new_cookie = 0;
207 fm.modify_cookie = false;
208 fm.table_id = 0;
209 fm.command = OFPFC_ADD;
210 fm.idle_timeout = 0;
211 fm.hard_timeout = 0;
212 fm.importance = 0;
213 fm.buffer_id = UINT32_MAX;
214 fm.out_port = OFPP_NONE;
215 fm.out_group = OFPG_ANY;
216 fm.flags = 0;
217 fm.ofpacts = &output.ofpact;
218 fm.ofpacts_len = sizeof output;
219 fm.delete_reason = 0;
220
221 msg = ofputil_encode_flow_mod(&fm, protocol);
222 error = rconn_send(sw->rconn, msg, NULL);
223 if (error) {
224 VLOG_INFO_RL(&rl, "%s: failed to add default flow (%s)",
225 rconn_get_name(sw->rconn), ovs_strerror(error));
226 }
227 }
228 if (sw->default_flows) {
229 struct ofpbuf *msg = NULL;
230 int error = 0;
231 size_t i;
232
233 /* If the initial protocol isn't good enough for default_flows, then
234 * pick one that will work and encode messages to set up that
235 * protocol.
236 *
237 * This could be improved by actually negotiating a mutually acceptable
238 * flow format with the switch, but that would require an asynchronous
239 * state machine. This version ought to work fine in practice. */
240 if (!(protocol & sw->usable_protocols)) {
241 enum ofputil_protocol want = rightmost_1bit(sw->usable_protocols);
242 while (!error) {
243 msg = ofputil_encode_set_protocol(protocol, want, &protocol);
244 if (!msg) {
245 break;
246 }
247 error = rconn_send(sw->rconn, msg, NULL);
248 }
249 }
250 if (protocol & sw->usable_protocols) {
251 for (i = 0; !error && i < sw->n_default_flows; i++) {
252 msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol);
253 error = rconn_send(sw->rconn, msg, NULL);
254 }
255
256 if (error) {
257 VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)",
258 rconn_get_name(sw->rconn), ovs_strerror(error));
259 }
260 } else {
261 VLOG_INFO_RL(&rl, "%s: failed to set usable protocol",
262 rconn_get_name(sw->rconn));
263 }
264 }
265 sw->protocol = protocol;
266 }
267
268 bool
269 lswitch_is_alive(const struct lswitch *sw)
270 {
271 return rconn_is_alive(sw->rconn);
272 }
273
274 /* Destroys 'sw'. */
275 void
276 lswitch_destroy(struct lswitch *sw)
277 {
278 if (sw) {
279 struct lswitch_port *node, *next;
280
281 rconn_destroy(sw->rconn);
282 HMAP_FOR_EACH_SAFE (node, next, hmap_node, &sw->queue_numbers) {
283 hmap_remove(&sw->queue_numbers, &node->hmap_node);
284 free(node);
285 }
286 shash_destroy(&sw->queue_names);
287 mac_learning_unref(sw->ml);
288 rconn_packet_counter_destroy(sw->queued);
289 free(sw);
290 }
291 }
292
293 /* Takes care of necessary 'sw' activity, except for receiving packets (which
294 * the caller must do). */
295 void
296 lswitch_run(struct lswitch *sw)
297 {
298 int i;
299
300 if (sw->ml) {
301 ovs_rwlock_wrlock(&sw->ml->rwlock);
302 mac_learning_run(sw->ml);
303 ovs_rwlock_unlock(&sw->ml->rwlock);
304 }
305
306 rconn_run(sw->rconn);
307
308 if (sw->state == S_CONNECTING) {
309 if (rconn_get_version(sw->rconn) != -1) {
310 lswitch_handshake(sw);
311 sw->state = S_FEATURES_REPLY;
312 }
313 return;
314 }
315
316 for (i = 0; i < 50; i++) {
317 struct ofpbuf *msg;
318
319 msg = rconn_recv(sw->rconn);
320 if (!msg) {
321 break;
322 }
323
324 if (!sw->mute) {
325 lswitch_process_packet(sw, msg);
326 }
327 ofpbuf_delete(msg);
328 }
329 }
330
331 void
332 lswitch_wait(struct lswitch *sw)
333 {
334 if (sw->ml) {
335 ovs_rwlock_rdlock(&sw->ml->rwlock);
336 mac_learning_wait(sw->ml);
337 ovs_rwlock_unlock(&sw->ml->rwlock);
338 }
339 rconn_run_wait(sw->rconn);
340 rconn_recv_wait(sw->rconn);
341 }
342
343 /* Processes 'msg', which should be an OpenFlow received on 'rconn', according
344 * to the learning switch state in 'sw'. The most likely result of processing
345 * is that flow-setup and packet-out OpenFlow messages will be sent out on
346 * 'rconn'. */
347 static void
348 lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg)
349 {
350 enum ofptype type;
351 struct ofpbuf b;
352
353 b = *msg;
354 if (ofptype_pull(&type, &b)) {
355 return;
356 }
357
358 if (sw->state == S_FEATURES_REPLY
359 && type != OFPTYPE_ECHO_REQUEST
360 && type != OFPTYPE_FEATURES_REPLY) {
361 return;
362 }
363
364 switch (type) {
365 case OFPTYPE_ECHO_REQUEST:
366 process_echo_request(sw, ofpbuf_data(msg));
367 break;
368
369 case OFPTYPE_FEATURES_REPLY:
370 if (sw->state == S_FEATURES_REPLY) {
371 if (!process_switch_features(sw, ofpbuf_data(msg))) {
372 sw->state = S_SWITCHING;
373 } else {
374 rconn_disconnect(sw->rconn);
375 }
376 }
377 break;
378
379 case OFPTYPE_PACKET_IN:
380 process_packet_in(sw, ofpbuf_data(msg));
381 break;
382
383 case OFPTYPE_FLOW_REMOVED:
384 /* Nothing to do. */
385 break;
386
387 case OFPTYPE_HELLO:
388 case OFPTYPE_ERROR:
389 case OFPTYPE_ECHO_REPLY:
390 case OFPTYPE_FEATURES_REQUEST:
391 case OFPTYPE_GET_CONFIG_REQUEST:
392 case OFPTYPE_GET_CONFIG_REPLY:
393 case OFPTYPE_SET_CONFIG:
394 case OFPTYPE_PORT_STATUS:
395 case OFPTYPE_PACKET_OUT:
396 case OFPTYPE_FLOW_MOD:
397 case OFPTYPE_GROUP_MOD:
398 case OFPTYPE_PORT_MOD:
399 case OFPTYPE_TABLE_MOD:
400 case OFPTYPE_BARRIER_REQUEST:
401 case OFPTYPE_BARRIER_REPLY:
402 case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
403 case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
404 case OFPTYPE_DESC_STATS_REQUEST:
405 case OFPTYPE_DESC_STATS_REPLY:
406 case OFPTYPE_FLOW_STATS_REQUEST:
407 case OFPTYPE_FLOW_STATS_REPLY:
408 case OFPTYPE_AGGREGATE_STATS_REQUEST:
409 case OFPTYPE_AGGREGATE_STATS_REPLY:
410 case OFPTYPE_TABLE_STATS_REQUEST:
411 case OFPTYPE_TABLE_STATS_REPLY:
412 case OFPTYPE_PORT_STATS_REQUEST:
413 case OFPTYPE_PORT_STATS_REPLY:
414 case OFPTYPE_QUEUE_STATS_REQUEST:
415 case OFPTYPE_QUEUE_STATS_REPLY:
416 case OFPTYPE_PORT_DESC_STATS_REQUEST:
417 case OFPTYPE_PORT_DESC_STATS_REPLY:
418 case OFPTYPE_ROLE_REQUEST:
419 case OFPTYPE_ROLE_REPLY:
420 case OFPTYPE_ROLE_STATUS:
421 case OFPTYPE_SET_FLOW_FORMAT:
422 case OFPTYPE_FLOW_MOD_TABLE_ID:
423 case OFPTYPE_SET_PACKET_IN_FORMAT:
424 case OFPTYPE_FLOW_AGE:
425 case OFPTYPE_SET_CONTROLLER_ID:
426 case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
427 case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
428 case OFPTYPE_FLOW_MONITOR_CANCEL:
429 case OFPTYPE_FLOW_MONITOR_PAUSED:
430 case OFPTYPE_FLOW_MONITOR_RESUMED:
431 case OFPTYPE_GET_ASYNC_REQUEST:
432 case OFPTYPE_GET_ASYNC_REPLY:
433 case OFPTYPE_SET_ASYNC_CONFIG:
434 case OFPTYPE_METER_MOD:
435 case OFPTYPE_GROUP_STATS_REQUEST:
436 case OFPTYPE_GROUP_STATS_REPLY:
437 case OFPTYPE_GROUP_DESC_STATS_REQUEST:
438 case OFPTYPE_GROUP_DESC_STATS_REPLY:
439 case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
440 case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
441 case OFPTYPE_METER_STATS_REQUEST:
442 case OFPTYPE_METER_STATS_REPLY:
443 case OFPTYPE_METER_CONFIG_STATS_REQUEST:
444 case OFPTYPE_METER_CONFIG_STATS_REPLY:
445 case OFPTYPE_METER_FEATURES_STATS_REQUEST:
446 case OFPTYPE_METER_FEATURES_STATS_REPLY:
447 case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
448 case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
449 case OFPTYPE_BUNDLE_CONTROL:
450 case OFPTYPE_BUNDLE_ADD_MESSAGE:
451 default:
452 if (VLOG_IS_DBG_ENABLED()) {
453 char *s = ofp_to_string(ofpbuf_data(msg), ofpbuf_size(msg), 2);
454 VLOG_DBG_RL(&rl, "%016llx: OpenFlow packet ignored: %s",
455 sw->datapath_id, s);
456 free(s);
457 }
458 }
459 }
460 \f
461 static void
462 send_features_request(struct lswitch *sw)
463 {
464 struct ofpbuf *b;
465 struct ofp_switch_config *osc;
466 int ofp_version = rconn_get_version(sw->rconn);
467
468 ovs_assert(ofp_version > 0 && ofp_version < 0xff);
469
470 /* Send OFPT_FEATURES_REQUEST. */
471 b = ofpraw_alloc(OFPRAW_OFPT_FEATURES_REQUEST, ofp_version, 0);
472 queue_tx(sw, b);
473
474 /* Send OFPT_SET_CONFIG. */
475 b = ofpraw_alloc(OFPRAW_OFPT_SET_CONFIG, ofp_version, sizeof *osc);
476 osc = ofpbuf_put_zeros(b, sizeof *osc);
477 osc->miss_send_len = htons(OFP_DEFAULT_MISS_SEND_LEN);
478 queue_tx(sw, b);
479 }
480
481 static void
482 queue_tx(struct lswitch *sw, struct ofpbuf *b)
483 {
484 int retval = rconn_send_with_limit(sw->rconn, b, sw->queued, 10);
485 if (retval && retval != ENOTCONN) {
486 if (retval == EAGAIN) {
487 VLOG_INFO_RL(&rl, "%016llx: %s: tx queue overflow",
488 sw->datapath_id, rconn_get_name(sw->rconn));
489 } else {
490 VLOG_WARN_RL(&rl, "%016llx: %s: send: %s",
491 sw->datapath_id, rconn_get_name(sw->rconn),
492 ovs_strerror(retval));
493 }
494 }
495 }
496
497 static enum ofperr
498 process_switch_features(struct lswitch *sw, struct ofp_header *oh)
499 {
500 struct ofputil_switch_features features;
501 struct ofputil_phy_port port;
502 enum ofperr error;
503 struct ofpbuf b;
504
505 error = ofputil_decode_switch_features(oh, &features, &b);
506 if (error) {
507 VLOG_ERR("received invalid switch feature reply (%s)",
508 ofperr_to_string(error));
509 return error;
510 }
511
512 sw->datapath_id = features.datapath_id;
513
514 while (!ofputil_pull_phy_port(oh->version, &b, &port)) {
515 struct lswitch_port *lp = shash_find_data(&sw->queue_names, port.name);
516 if (lp && hmap_node_is_null(&lp->hmap_node)) {
517 lp->port_no = port.port_no;
518 hmap_insert(&sw->queue_numbers, &lp->hmap_node,
519 hash_ofp_port(lp->port_no));
520 }
521 }
522 return 0;
523 }
524
525 static ofp_port_t
526 lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
527 {
528 ofp_port_t out_port;
529
530 /* Learn the source MAC. */
531 if (sw->ml) {
532 ovs_rwlock_wrlock(&sw->ml->rwlock);
533 if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) {
534 struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src,
535 0);
536 if (get_mac_entry_ofp_port(sw->ml, mac)
537 != flow->in_port.ofp_port) {
538 VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on "
539 "port %"PRIu16, sw->datapath_id,
540 ETH_ADDR_ARGS(flow->dl_src),
541 flow->in_port.ofp_port);
542
543 set_mac_entry_ofp_port(sw->ml, mac, flow->in_port.ofp_port);
544 }
545 }
546 ovs_rwlock_unlock(&sw->ml->rwlock);
547 }
548
549 /* Drop frames for reserved multicast addresses. */
550 if (eth_addr_is_reserved(flow->dl_dst)) {
551 return OFPP_NONE;
552 }
553
554 out_port = OFPP_FLOOD;
555 if (sw->ml) {
556 struct mac_entry *mac;
557
558 ovs_rwlock_rdlock(&sw->ml->rwlock);
559 mac = mac_learning_lookup(sw->ml, flow->dl_dst, 0);
560 if (mac) {
561 out_port = get_mac_entry_ofp_port(sw->ml, mac);
562 if (out_port == flow->in_port.ofp_port) {
563 /* Don't send a packet back out its input port. */
564 ovs_rwlock_unlock(&sw->ml->rwlock);
565 return OFPP_NONE;
566 }
567 }
568 ovs_rwlock_unlock(&sw->ml->rwlock);
569 }
570
571 /* Check if we need to use "NORMAL" action. */
572 if (sw->action_normal && out_port != OFPP_FLOOD) {
573 return OFPP_NORMAL;
574 }
575
576 return out_port;
577 }
578
579 static uint32_t
580 get_queue_id(const struct lswitch *sw, ofp_port_t in_port)
581 {
582 const struct lswitch_port *port;
583
584 HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_ofp_port(in_port),
585 &sw->queue_numbers) {
586 if (port->port_no == in_port) {
587 return port->queue_id;
588 }
589 }
590
591 return sw->default_queue;
592 }
593
594 static void
595 process_packet_in(struct lswitch *sw, const struct ofp_header *oh)
596 {
597 struct ofputil_packet_in pi;
598 uint32_t queue_id;
599 ofp_port_t out_port;
600
601 uint64_t ofpacts_stub[64 / 8];
602 struct ofpbuf ofpacts;
603
604 struct ofputil_packet_out po;
605 enum ofperr error;
606
607 struct ofpbuf pkt;
608 struct flow flow;
609
610 error = ofputil_decode_packet_in(&pi, oh);
611 if (error) {
612 VLOG_WARN_RL(&rl, "failed to decode packet-in: %s",
613 ofperr_to_string(error));
614 return;
615 }
616
617 /* Ignore packets sent via output to OFPP_CONTROLLER. This library never
618 * uses such an action. You never know what experiments might be going on,
619 * though, and it seems best not to interfere with them. */
620 if (pi.reason != OFPR_NO_MATCH) {
621 return;
622 }
623
624 /* Extract flow data from 'opi' into 'flow'. */
625 ofpbuf_use_const(&pkt, pi.packet, pi.packet_len);
626 flow_extract(&pkt, NULL, &flow);
627 flow.in_port.ofp_port = pi.fmd.in_port;
628 flow.tunnel.tun_id = pi.fmd.tun_id;
629
630 /* Choose output port. */
631 out_port = lswitch_choose_destination(sw, &flow);
632
633 /* Make actions. */
634 queue_id = get_queue_id(sw, pi.fmd.in_port);
635 ofpbuf_use_stack(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
636 if (out_port == OFPP_NONE) {
637 /* No actions. */
638 } else if (queue_id == UINT32_MAX
639 || ofp_to_u16(out_port) >= ofp_to_u16(OFPP_MAX)) {
640 ofpact_put_OUTPUT(&ofpacts)->port = out_port;
641 } else {
642 struct ofpact_enqueue *enqueue = ofpact_put_ENQUEUE(&ofpacts);
643 enqueue->port = out_port;
644 enqueue->queue = queue_id;
645 }
646 ofpact_pad(&ofpacts);
647
648 /* Prepare packet_out in case we need one. */
649 po.buffer_id = pi.buffer_id;
650 if (po.buffer_id == UINT32_MAX) {
651 po.packet = ofpbuf_data(&pkt);
652 po.packet_len = ofpbuf_size(&pkt);
653 } else {
654 po.packet = NULL;
655 po.packet_len = 0;
656 }
657 po.in_port = pi.fmd.in_port;
658 po.ofpacts = ofpbuf_data(&ofpacts);
659 po.ofpacts_len = ofpbuf_size(&ofpacts);
660
661 /* Send the packet, and possibly the whole flow, to the output port. */
662 if (sw->max_idle >= 0 && (!sw->ml || out_port != OFPP_FLOOD)) {
663 struct ofputil_flow_mod fm;
664 struct ofpbuf *buffer;
665
666 /* The output port is known, or we always flood everything, so add a
667 * new flow. */
668 memset(&fm, 0, sizeof fm);
669 match_init(&fm.match, &flow, &sw->wc);
670 ofputil_normalize_match_quiet(&fm.match);
671 fm.priority = 1; /* Must be > 0 because of table-miss flow entry. */
672 fm.table_id = 0xff;
673 fm.command = OFPFC_ADD;
674 fm.idle_timeout = sw->max_idle;
675 fm.buffer_id = pi.buffer_id;
676 fm.out_port = OFPP_NONE;
677 fm.ofpacts = ofpbuf_data(&ofpacts);
678 fm.ofpacts_len = ofpbuf_size(&ofpacts);
679 buffer = ofputil_encode_flow_mod(&fm, sw->protocol);
680
681 queue_tx(sw, buffer);
682
683 /* If the switch didn't buffer the packet, we need to send a copy. */
684 if (pi.buffer_id == UINT32_MAX && out_port != OFPP_NONE) {
685 queue_tx(sw, ofputil_encode_packet_out(&po, sw->protocol));
686 }
687 } else {
688 /* We don't know that MAC, or we don't set up flows. Send along the
689 * packet without setting up a flow. */
690 if (pi.buffer_id != UINT32_MAX || out_port != OFPP_NONE) {
691 queue_tx(sw, ofputil_encode_packet_out(&po, sw->protocol));
692 }
693 }
694 }
695
696 static void
697 process_echo_request(struct lswitch *sw, const struct ofp_header *rq)
698 {
699 queue_tx(sw, make_echo_reply(rq));
700 }
701
702 static ofp_port_t
703 get_mac_entry_ofp_port(const struct mac_learning *ml,
704 const struct mac_entry *e)
705 OVS_REQ_RDLOCK(ml->rwlock)
706 {
707 void *port = mac_entry_get_port(ml, e);
708 return (OVS_FORCE ofp_port_t) (uintptr_t) port;
709 }
710
711 static void
712 set_mac_entry_ofp_port(struct mac_learning *ml,
713 struct mac_entry *e, ofp_port_t ofp_port)
714 OVS_REQ_WRLOCK(ml->rwlock)
715 {
716 mac_entry_set_port(ml, e, (void *) (OVS_FORCE uintptr_t) ofp_port);
717 }