2
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
2
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
49
49
struct lswitch_port {
50
50
struct hmap_node hmap_node; /* Hash node for port number. */
51
uint16_t port_no; /* OpenFlow port number, in host byte order. */
51
ofp_port_t port_no; /* OpenFlow port number. */
52
52
uint32_t queue_id; /* OpenFlow queue number. */
210
210
VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)",
211
rconn_get_name(sw->rconn), strerror(error));
211
rconn_get_name(sw->rconn), ovs_strerror(error));
214
214
VLOG_INFO_RL(&rl, "%s: failed to set usable protocol",
283
285
lswitch_wait(struct lswitch *sw)
288
ovs_rwlock_rdlock(&sw->ml->rwlock);
286
289
mac_learning_wait(sw->ml);
290
ovs_rwlock_unlock(&sw->ml->rwlock);
288
292
rconn_run_wait(sw->rconn);
289
293
rconn_recv_wait(sw->rconn);
378
382
case OFPTYPE_GET_ASYNC_REPLY:
379
383
case OFPTYPE_SET_ASYNC_CONFIG:
380
384
case OFPTYPE_METER_MOD:
381
case OFPTYPE_GROUP_REQUEST:
382
case OFPTYPE_GROUP_REPLY:
383
case OFPTYPE_GROUP_DESC_REQUEST:
384
case OFPTYPE_GROUP_DESC_REPLY:
385
case OFPTYPE_GROUP_FEATURES_REQUEST:
386
case OFPTYPE_GROUP_FEATURES_REPLY:
387
case OFPTYPE_METER_REQUEST:
388
case OFPTYPE_METER_REPLY:
389
case OFPTYPE_METER_CONFIG_REQUEST:
390
case OFPTYPE_METER_CONFIG_REPLY:
391
case OFPTYPE_METER_FEATURES_REQUEST:
392
case OFPTYPE_METER_FEATURES_REPLY:
393
case OFPTYPE_TABLE_FEATURES_REQUEST:
394
case OFPTYPE_TABLE_FEATURES_REPLY:
385
case OFPTYPE_GROUP_STATS_REQUEST:
386
case OFPTYPE_GROUP_STATS_REPLY:
387
case OFPTYPE_GROUP_DESC_STATS_REQUEST:
388
case OFPTYPE_GROUP_DESC_STATS_REPLY:
389
case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
390
case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
391
case OFPTYPE_METER_STATS_REQUEST:
392
case OFPTYPE_METER_STATS_REPLY:
393
case OFPTYPE_METER_CONFIG_STATS_REQUEST:
394
case OFPTYPE_METER_CONFIG_STATS_REPLY:
395
case OFPTYPE_METER_FEATURES_STATS_REQUEST:
396
case OFPTYPE_METER_FEATURES_STATS_REPLY:
397
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
398
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
396
400
if (VLOG_IS_DBG_ENABLED()) {
397
401
char *s = ofp_to_string(msg->data, msg->size, 2);
460
464
if (lp && hmap_node_is_null(&lp->hmap_node)) {
461
465
lp->port_no = port.port_no;
462
466
hmap_insert(&sw->queue_numbers, &lp->hmap_node,
463
hash_int(lp->port_no, 0));
467
hash_ofp_port(lp->port_no));
470
474
lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
474
478
/* Learn the source MAC. */
479
ovs_rwlock_wrlock(&sw->ml->rwlock);
475
480
if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) {
476
481
struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src, 0);
477
if (mac_entry_is_new(mac) || mac->port.i != flow->in_port) {
482
if (mac_entry_is_new(mac)
483
|| mac->port.ofp_port != flow->in_port.ofp_port) {
478
484
VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on "
479
485
"port %"PRIu16, sw->datapath_id,
480
ETH_ADDR_ARGS(flow->dl_src), flow->in_port);
486
ETH_ADDR_ARGS(flow->dl_src), flow->in_port.ofp_port);
482
mac->port.i = flow->in_port;
488
mac->port.ofp_port = flow->in_port.ofp_port;
483
489
mac_learning_changed(sw->ml, mac);
492
ovs_rwlock_unlock(&sw->ml->rwlock);
487
494
/* Drop frames for reserved multicast addresses. */
488
495
if (eth_addr_is_reserved(flow->dl_dst)) {
494
501
struct mac_entry *mac;
503
ovs_rwlock_rdlock(&sw->ml->rwlock);
496
504
mac = mac_learning_lookup(sw->ml, flow->dl_dst, 0, NULL);
498
out_port = mac->port.i;
499
if (out_port == flow->in_port) {
506
out_port = mac->port.ofp_port;
507
if (out_port == flow->in_port.ofp_port) {
500
508
/* Don't send a packet back out its input port. */
509
ovs_rwlock_unlock(&sw->ml->rwlock);
501
510
return OFPP_NONE;
513
ovs_rwlock_unlock(&sw->ml->rwlock);
506
516
/* Check if we need to use "NORMAL" action. */
515
get_queue_id(const struct lswitch *sw, uint16_t in_port)
525
get_queue_id(const struct lswitch *sw, ofp_port_t in_port)
517
527
const struct lswitch_port *port;
519
HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_int(in_port, 0),
529
HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_ofp_port(in_port),
520
530
&sw->queue_numbers) {
521
531
if (port->port_no == in_port) {
522
532
return port->queue_id;
559
570
/* Extract flow data from 'opi' into 'flow'. */
560
571
ofpbuf_use_const(&pkt, pi.packet, pi.packet_len);
561
flow_extract(&pkt, 0, 0, NULL, pi.fmd.in_port, &flow);
572
in_port_.ofp_port = pi.fmd.in_port;
573
flow_extract(&pkt, 0, 0, NULL, &in_port_, &flow);
562
574
flow.tunnel.tun_id = pi.fmd.tun_id;
564
576
/* Choose output port. */
569
581
ofpbuf_use_stack(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
570
582
if (out_port == OFPP_NONE) {
571
583
/* No actions. */
572
} else if (queue_id == UINT32_MAX || out_port >= OFPP_MAX) {
584
} else if (queue_id == UINT32_MAX
585
|| ofp_to_u16(out_port) >= ofp_to_u16(OFPP_MAX)) {
573
586
ofpact_put_OUTPUT(&ofpacts)->port = out_port;
575
588
struct ofpact_enqueue *enqueue = ofpact_put_ENQUEUE(&ofpacts);