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

« back to all changes in this revision

Viewing changes to ofproto/ofproto-dpif-sflow.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) 2009, 2010, 2011, 2012 Nicira, Inc.
 
2
 * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3
3
 * Copyright (c) 2009 InMon Corp.
4
4
 *
5
5
 * Licensed under the Apache License, Version 2.0 (the "License");
42
42
 
43
43
VLOG_DEFINE_THIS_MODULE(sflow);
44
44
 
 
45
static struct ovs_mutex mutex;
 
46
 
45
47
struct dpif_sflow_port {
46
48
    struct hmap_node hmap_node; /* In struct dpif_sflow's "ports" hmap. */
47
49
    SFLDataSource_instance dsi; /* sFlow library's notion of port number. */
48
50
    struct ofport *ofport;      /* To retrive port stats. */
49
 
    uint32_t odp_port;
 
51
    odp_port_t odp_port;
50
52
};
51
53
 
52
54
struct dpif_sflow {
57
59
    size_t n_flood, n_all;
58
60
    struct hmap ports;          /* Contains "struct dpif_sflow_port"s. */
59
61
    uint32_t probability;
 
62
    atomic_int ref_cnt;
60
63
};
61
64
 
62
65
static void dpif_sflow_del_port__(struct dpif_sflow *,
142
145
}
143
146
 
144
147
static struct dpif_sflow_port *
145
 
dpif_sflow_find_port(const struct dpif_sflow *ds, uint32_t odp_port)
 
148
dpif_sflow_find_port(const struct dpif_sflow *ds, odp_port_t odp_port)
 
149
    OVS_REQ_WRLOCK(&mutex)
146
150
{
147
151
    struct dpif_sflow_port *dsp;
148
152
 
149
 
    HMAP_FOR_EACH_IN_BUCKET (dsp, hmap_node,
150
 
                             hash_int(odp_port, 0), &ds->ports) {
 
153
    HMAP_FOR_EACH_IN_BUCKET (dsp, hmap_node, hash_odp_port(odp_port),
 
154
                             &ds->ports) {
151
155
        if (dsp->odp_port == odp_port) {
152
156
            return dsp;
153
157
        }
158
162
static void
159
163
sflow_agent_get_counters(void *ds_, SFLPoller *poller,
160
164
                         SFL_COUNTERS_SAMPLE_TYPE *cs)
 
165
    OVS_REQ_WRLOCK(&mutex)
161
166
{
162
167
    struct dpif_sflow *ds = ds_;
163
168
    SFLCounters_sample_element elem;
167
172
    struct netdev_stats stats;
168
173
    enum netdev_flags flags;
169
174
 
170
 
    dsp = dpif_sflow_find_port(ds, poller->bridgePort);
 
175
    dsp = dpif_sflow_find_port(ds, u32_to_odp(poller->bridgePort));
171
176
    if (!dsp) {
172
177
        return;
173
178
    }
270
275
    return true;
271
276
}
272
277
 
273
 
void
274
 
dpif_sflow_clear(struct dpif_sflow *ds)
 
278
static void
 
279
dpif_sflow_clear__(struct dpif_sflow *ds) OVS_REQ_WRLOCK(mutex)
275
280
{
276
281
    if (ds->sflow_agent) {
277
282
        sfl_agent_release(ds->sflow_agent);
286
291
    ds->probability = 0;
287
292
}
288
293
 
 
294
void
 
295
dpif_sflow_clear(struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
 
296
{
 
297
    ovs_mutex_lock(&mutex);
 
298
    dpif_sflow_clear__(ds);
 
299
    ovs_mutex_unlock(&mutex);
 
300
}
 
301
 
289
302
bool
290
 
dpif_sflow_is_enabled(const struct dpif_sflow *ds)
 
303
dpif_sflow_is_enabled(const struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
291
304
{
292
 
    return ds->collectors != NULL;
 
305
    bool enabled;
 
306
 
 
307
    ovs_mutex_lock(&mutex);
 
308
    enabled = ds->collectors != NULL;
 
309
    ovs_mutex_unlock(&mutex);
 
310
    return enabled;
293
311
}
294
312
 
295
313
struct dpif_sflow *
296
314
dpif_sflow_create(void)
297
315
{
 
316
    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
298
317
    struct dpif_sflow *ds;
299
318
 
 
319
    if (ovsthread_once_start(&once)) {
 
320
        ovs_mutex_init(&mutex, PTHREAD_MUTEX_RECURSIVE);
 
321
        ovsthread_once_done(&once);
 
322
    }
 
323
 
300
324
    ds = xcalloc(1, sizeof *ds);
301
325
    ds->next_tick = time_now() + 1;
302
326
    hmap_init(&ds->ports);
303
327
    ds->probability = 0;
304
328
    route_table_register();
305
 
 
 
329
    atomic_init(&ds->ref_cnt, 1);
 
330
 
 
331
    return ds;
 
332
}
 
333
 
 
334
struct dpif_sflow *
 
335
dpif_sflow_ref(const struct dpif_sflow *ds_)
 
336
{
 
337
    struct dpif_sflow *ds = CONST_CAST(struct dpif_sflow *, ds_);
 
338
    if (ds) {
 
339
        int orig;
 
340
        atomic_add(&ds->ref_cnt, 1, &orig);
 
341
        ovs_assert(orig > 0);
 
342
    }
306
343
    return ds;
307
344
}
308
345
 
310
347
 * a value of %UINT32_MAX samples all packets and intermediate values sample
311
348
 * intermediate fractions of packets. */
312
349
uint32_t
313
 
dpif_sflow_get_probability(const struct dpif_sflow *ds)
 
350
dpif_sflow_get_probability(const struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
314
351
{
315
 
    return ds->probability;
 
352
    uint32_t probability;
 
353
    ovs_mutex_lock(&mutex);
 
354
    probability = ds->probability;
 
355
    ovs_mutex_unlock(&mutex);
 
356
    return probability;
316
357
}
317
358
 
318
359
void
319
 
dpif_sflow_destroy(struct dpif_sflow *ds)
 
360
dpif_sflow_unref(struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
320
361
{
321
 
    if (ds) {
 
362
    int orig;
 
363
 
 
364
    if (!ds) {
 
365
        return;
 
366
    }
 
367
 
 
368
    atomic_sub(&ds->ref_cnt, 1, &orig);
 
369
    ovs_assert(orig > 0);
 
370
    if (orig == 1) {
322
371
        struct dpif_sflow_port *dsp, *next;
323
372
 
324
373
        route_table_unregister();
333
382
 
334
383
static void
335
384
dpif_sflow_add_poller(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
 
385
    OVS_REQ_WRLOCK(mutex)
336
386
{
337
387
    SFLPoller *poller = sfl_agent_addPoller(ds->sflow_agent, &dsp->dsi, ds,
338
388
                                            sflow_agent_get_counters);
339
389
    sfl_poller_set_sFlowCpInterval(poller, ds->options->polling_interval);
340
390
    sfl_poller_set_sFlowCpReceiver(poller, RECEIVER_INDEX);
341
 
    sfl_poller_set_bridgePort(poller, dsp->odp_port);
 
391
    sfl_poller_set_bridgePort(poller, odp_to_u32(dsp->odp_port));
342
392
}
343
393
 
344
394
void
345
395
dpif_sflow_add_port(struct dpif_sflow *ds, struct ofport *ofport,
346
 
                    uint32_t odp_port)
 
396
                    odp_port_t odp_port) OVS_EXCLUDED(mutex)
347
397
{
348
398
    struct dpif_sflow_port *dsp;
349
399
    int ifindex;
350
400
 
 
401
    ovs_mutex_lock(&mutex);
351
402
    dpif_sflow_del_port(ds, odp_port);
352
403
 
353
404
    ifindex = netdev_get_ifindex(ofport->netdev);
354
405
 
355
406
    if (ifindex <= 0) {
356
407
        /* Not an ifindex port, so do not add a cross-reference to it here */
357
 
        return;
 
408
        goto out;
358
409
    }
359
410
 
360
411
    /* Add to table of ports. */
362
413
    dsp->ofport = ofport;
363
414
    dsp->odp_port = odp_port;
364
415
    SFL_DS_SET(dsp->dsi, SFL_DSCLASS_IFINDEX, ifindex, 0);
365
 
    hmap_insert(&ds->ports, &dsp->hmap_node, hash_int(odp_port, 0));
 
416
    hmap_insert(&ds->ports, &dsp->hmap_node, hash_odp_port(odp_port));
366
417
 
367
418
    /* Add poller. */
368
419
    if (ds->sflow_agent) {
369
420
        dpif_sflow_add_poller(ds, dsp);
370
421
    }
 
422
 
 
423
out:
 
424
    ovs_mutex_unlock(&mutex);
371
425
}
372
426
 
373
427
static void
374
428
dpif_sflow_del_port__(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
 
429
    OVS_REQ_WRLOCK(mutex)
375
430
{
376
431
    if (ds->sflow_agent) {
377
432
        sfl_agent_removePoller(ds->sflow_agent, &dsp->dsi);
382
437
}
383
438
 
384
439
void
385
 
dpif_sflow_del_port(struct dpif_sflow *ds, uint32_t odp_port)
 
440
dpif_sflow_del_port(struct dpif_sflow *ds, odp_port_t odp_port)
 
441
    OVS_EXCLUDED(mutex)
386
442
{
387
 
    struct dpif_sflow_port *dsp = dpif_sflow_find_port(ds, odp_port);
 
443
    struct dpif_sflow_port *dsp;
 
444
 
 
445
    ovs_mutex_lock(&mutex);
 
446
    dsp = dpif_sflow_find_port(ds, odp_port);
388
447
    if (dsp) {
389
448
        dpif_sflow_del_port__(ds, dsp);
390
449
    }
 
450
    ovs_mutex_unlock(&mutex);
391
451
}
392
452
 
393
453
void
394
454
dpif_sflow_set_options(struct dpif_sflow *ds,
395
455
                       const struct ofproto_sflow_options *options)
 
456
    OVS_EXCLUDED(mutex)
396
457
{
397
458
    struct dpif_sflow_port *dsp;
398
459
    bool options_changed;
403
464
    uint32_t dsIndex;
404
465
    SFLSampler *sampler;
405
466
 
 
467
    ovs_mutex_lock(&mutex);
406
468
    if (sset_is_empty(&options->targets) || !options->sampling_rate) {
407
469
        /* No point in doing any work if there are no targets or nothing to
408
470
         * sample. */
409
 
        dpif_sflow_clear(ds);
410
 
        return;
 
471
        dpif_sflow_clear__(ds);
 
472
        goto out;
411
473
    }
412
474
 
413
475
    options_changed = (!ds->options
424
486
        if (ds->collectors == NULL) {
425
487
            VLOG_WARN_RL(&rl, "no collectors could be initialized, "
426
488
                         "sFlow disabled");
427
 
            dpif_sflow_clear(ds);
428
 
            return;
 
489
            dpif_sflow_clear__(ds);
 
490
            goto out;
429
491
        }
430
492
    }
431
493
 
433
495
    if (!sflow_choose_agent_address(options->agent_device,
434
496
                                    &options->targets,
435
497
                                    options->control_ip, &agentIP)) {
436
 
        dpif_sflow_clear(ds);
437
 
        return;
 
498
        dpif_sflow_clear__(ds);
 
499
        goto out;
438
500
    }
439
501
 
440
502
    /* Avoid reconfiguring if options didn't change. */
441
503
    if (!options_changed) {
442
 
        return;
 
504
        goto out;
443
505
    }
444
506
    ofproto_sflow_options_destroy(ds->options);
445
507
    ds->options = ofproto_sflow_options_clone(options);
484
546
    HMAP_FOR_EACH (dsp, hmap_node, &ds->ports) {
485
547
        dpif_sflow_add_poller(ds, dsp);
486
548
    }
 
549
 
 
550
 
 
551
out:
 
552
    ovs_mutex_unlock(&mutex);
487
553
}
488
554
 
489
555
int
490
556
dpif_sflow_odp_port_to_ifindex(const struct dpif_sflow *ds,
491
 
                               uint32_t odp_port)
 
557
                               odp_port_t odp_port) OVS_EXCLUDED(mutex)
492
558
{
493
 
    struct dpif_sflow_port *dsp = dpif_sflow_find_port(ds, odp_port);
494
 
    return dsp ? SFL_DS_INDEX(dsp->dsi) : 0;
 
559
    struct dpif_sflow_port *dsp;
 
560
    int ret;
 
561
 
 
562
    ovs_mutex_lock(&mutex);
 
563
    dsp = dpif_sflow_find_port(ds, odp_port);
 
564
    ret = dsp ? SFL_DS_INDEX(dsp->dsi) : 0;
 
565
    ovs_mutex_unlock(&mutex);
 
566
    return ret;
495
567
}
496
568
 
497
569
void
498
570
dpif_sflow_received(struct dpif_sflow *ds, struct ofpbuf *packet,
499
 
                    const struct flow *flow, uint32_t odp_in_port,
 
571
                    const struct flow *flow, odp_port_t odp_in_port,
500
572
                    const union user_action_cookie *cookie)
 
573
    OVS_EXCLUDED(mutex)
501
574
{
502
575
    SFL_FLOW_SAMPLE_TYPE fs;
503
576
    SFLFlow_sample_element hdrElem;
507
580
    struct dpif_sflow_port *in_dsp;
508
581
    ovs_be16 vlan_tci;
509
582
 
 
583
    ovs_mutex_lock(&mutex);
510
584
    sampler = ds->sflow_agent->samplers;
511
585
    if (!sampler) {
512
 
        return;
 
586
        goto out;
513
587
    }
514
588
 
515
589
    /* Build a flow sample. */
558
632
    SFLADD_ELEMENT(&fs, &hdrElem);
559
633
    SFLADD_ELEMENT(&fs, &switchElem);
560
634
    sfl_sampler_writeFlowSample(sampler, &fs);
 
635
 
 
636
out:
 
637
    ovs_mutex_unlock(&mutex);
561
638
}
562
639
 
563
640
void
564
 
dpif_sflow_run(struct dpif_sflow *ds)
 
641
dpif_sflow_run(struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
565
642
{
566
 
    if (dpif_sflow_is_enabled(ds)) {
 
643
    ovs_mutex_lock(&mutex);
 
644
    if (ds->collectors != NULL) {
567
645
        time_t now = time_now();
568
646
        route_table_run();
569
647
        if (now >= ds->next_tick) {
571
649
            ds->next_tick = now + 1;
572
650
        }
573
651
    }
 
652
    ovs_mutex_unlock(&mutex);
574
653
}
575
654
 
576
655
void
577
 
dpif_sflow_wait(struct dpif_sflow *ds)
 
656
dpif_sflow_wait(struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
578
657
{
579
 
    if (dpif_sflow_is_enabled(ds)) {
 
658
    ovs_mutex_lock(&mutex);
 
659
    if (ds->collectors != NULL) {
580
660
        poll_timer_wait_until(ds->next_tick * 1000LL);
581
661
    }
 
662
    ovs_mutex_unlock(&mutex);
582
663
}