~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to lib/learning-switch.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
 
2
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3
3
 *
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.
48
48
 
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. */
53
53
};
54
54
 
208
208
 
209
209
            if (error) {
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));
212
212
            }
213
213
        } else {
214
214
            VLOG_INFO_RL(&rl, "%s: failed to set usable protocol",
237
237
            free(node);
238
238
        }
239
239
        shash_destroy(&sw->queue_names);
240
 
        mac_learning_destroy(sw->ml);
 
240
        mac_learning_unref(sw->ml);
241
241
        rconn_packet_counter_destroy(sw->queued);
242
242
        free(sw);
243
243
    }
251
251
    int i;
252
252
 
253
253
    if (sw->ml) {
 
254
        ovs_rwlock_wrlock(&sw->ml->rwlock);
254
255
        mac_learning_run(sw->ml, NULL);
 
256
        ovs_rwlock_unlock(&sw->ml->rwlock);
255
257
    }
256
258
 
257
259
    rconn_run(sw->rconn);
283
285
lswitch_wait(struct lswitch *sw)
284
286
{
285
287
    if (sw->ml) {
 
288
        ovs_rwlock_rdlock(&sw->ml->rwlock);
286
289
        mac_learning_wait(sw->ml);
 
290
        ovs_rwlock_unlock(&sw->ml->rwlock);
287
291
    }
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:
395
399
    default:
396
400
        if (VLOG_IS_DBG_ENABLED()) {
397
401
            char *s = ofp_to_string(msg->data, msg->size, 2);
433
437
        } else {
434
438
            VLOG_WARN_RL(&rl, "%016llx: %s: send: %s",
435
439
                         sw->datapath_id, rconn_get_name(sw->rconn),
436
 
                         strerror(retval));
 
440
                         ovs_strerror(retval));
437
441
        }
438
442
    }
439
443
}
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));
464
468
        }
465
469
    }
466
470
    return 0;
467
471
}
468
472
 
469
 
static uint16_t
 
473
static ofp_port_t
470
474
lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
471
475
{
472
 
    uint16_t out_port;
 
476
    ofp_port_t out_port;
473
477
 
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);
481
487
 
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);
484
490
        }
485
491
    }
 
492
    ovs_rwlock_unlock(&sw->ml->rwlock);
486
493
 
487
494
    /* Drop frames for reserved multicast addresses. */
488
495
    if (eth_addr_is_reserved(flow->dl_dst)) {
493
500
    if (sw->ml) {
494
501
        struct mac_entry *mac;
495
502
 
 
503
        ovs_rwlock_rdlock(&sw->ml->rwlock);
496
504
        mac = mac_learning_lookup(sw->ml, flow->dl_dst, 0, NULL);
497
505
        if (mac) {
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;
502
511
            }
503
512
        }
 
513
        ovs_rwlock_unlock(&sw->ml->rwlock);
504
514
    }
505
515
 
506
516
    /* Check if we need to use "NORMAL" action. */
512
522
}
513
523
 
514
524
static uint32_t
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)
516
526
{
517
527
    const struct lswitch_port *port;
518
528
 
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;
531
541
{
532
542
    struct ofputil_packet_in pi;
533
543
    uint32_t queue_id;
534
 
    uint16_t out_port;
 
544
    ofp_port_t out_port;
535
545
 
536
546
    uint64_t ofpacts_stub[64 / 8];
537
547
    struct ofpbuf ofpacts;
541
551
 
542
552
    struct ofpbuf pkt;
543
553
    struct flow flow;
 
554
    union flow_in_port in_port_;
544
555
 
545
556
    error = ofputil_decode_packet_in(&pi, oh);
546
557
    if (error) {
558
569
 
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;
563
575
 
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;
574
587
    } else {
575
588
        struct ofpact_enqueue *enqueue = ofpact_put_ENQUEUE(&ofpacts);