ovn-northd: Ensure that flows are added to correct types of datapaths.
[cascardo/ovs.git] / ofproto / ofproto-dpif-mirror.c
1 /* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc.
2  *
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:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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. */
14
15 #include <config.h>
16
17 #include "ofproto-dpif-mirror.h"
18
19 #include <errno.h>
20
21 #include "hmap.h"
22 #include "hmapx.h"
23 #include "ofproto.h"
24 #include "vlan-bitmap.h"
25 #include "openvswitch/vlog.h"
26
27 VLOG_DEFINE_THIS_MODULE(ofproto_dpif_mirror);
28
29 #define MIRROR_MASK_C(X) UINT32_C(X)
30 BUILD_ASSERT_DECL(sizeof(mirror_mask_t) * CHAR_BIT >= MAX_MIRRORS);
31
32 struct mbridge {
33     struct mirror *mirrors[MAX_MIRRORS];
34     struct hmap mbundles;
35
36     bool need_revalidate;
37     bool has_mirrors;
38
39     struct ovs_refcount ref_cnt;
40 };
41
42 struct mbundle {
43     struct hmap_node hmap_node; /* In parent 'mbridge' map. */
44     struct ofbundle *ofbundle;
45
46     mirror_mask_t src_mirrors;  /* Mirrors triggered when packet received. */
47     mirror_mask_t dst_mirrors;  /* Mirrors triggered when packet sent. */
48     mirror_mask_t mirror_out;   /* Mirrors that output to this mbundle. */
49 };
50
51 struct mirror {
52     struct mbridge *mbridge;    /* Owning ofproto. */
53     size_t idx;                 /* In ofproto's "mirrors" array. */
54     void *aux;                  /* Key supplied by ofproto's client. */
55
56     /* Selection criteria. */
57     struct hmapx srcs;          /* Contains "struct mbundle*"s. */
58     struct hmapx dsts;          /* Contains "struct mbundle*"s. */
59     unsigned long *vlans;       /* Bitmap of chosen VLANs, NULL selects all. */
60
61     /* Output (exactly one of out == NULL and out_vlan == -1 is true). */
62     struct mbundle *out;        /* Output port or NULL. */
63     int out_vlan;               /* Output VLAN or -1. */
64     uint16_t snaplen;           /* Max per mirrored packet size in byte,
65                                    set to 0 equals 65535. */
66     mirror_mask_t dup_mirrors;  /* Bitmap of mirrors with the same output. */
67
68     /* Counters. */
69     int64_t packet_count;       /* Number of packets sent. */
70     int64_t byte_count;         /* Number of bytes sent. */
71 };
72
73 static struct mirror *mirror_lookup(struct mbridge *, void *aux);
74 static struct mbundle *mbundle_lookup(const struct mbridge *,
75                                       struct ofbundle *);
76 static void mbundle_lookup_multiple(const struct mbridge *, struct ofbundle **,
77                                   size_t n_bundles, struct hmapx *mbundles);
78 static int mirror_scan(struct mbridge *);
79 static void mirror_update_dups(struct mbridge *);
80
81 struct mbridge *
82 mbridge_create(void)
83 {
84     struct mbridge *mbridge;
85
86     mbridge = xzalloc(sizeof *mbridge);
87     ovs_refcount_init(&mbridge->ref_cnt);
88
89     hmap_init(&mbridge->mbundles);
90     return mbridge;
91 }
92
93 struct mbridge *
94 mbridge_ref(const struct mbridge *mbridge_)
95 {
96     struct mbridge *mbridge = CONST_CAST(struct mbridge *, mbridge_);
97     if (mbridge) {
98         ovs_refcount_ref(&mbridge->ref_cnt);
99     }
100     return mbridge;
101 }
102
103 void
104 mbridge_unref(struct mbridge *mbridge)
105 {
106     struct mbundle *mbundle, *next;
107     size_t i;
108
109     if (!mbridge) {
110         return;
111     }
112
113     if (ovs_refcount_unref(&mbridge->ref_cnt) == 1) {
114         for (i = 0; i < MAX_MIRRORS; i++) {
115             if (mbridge->mirrors[i]) {
116                 mirror_destroy(mbridge, mbridge->mirrors[i]->aux);
117             }
118         }
119
120         HMAP_FOR_EACH_SAFE (mbundle, next, hmap_node, &mbridge->mbundles) {
121             mbridge_unregister_bundle(mbridge, mbundle->ofbundle);
122         }
123
124         hmap_destroy(&mbridge->mbundles);
125         free(mbridge);
126     }
127 }
128
129 bool
130 mbridge_has_mirrors(struct mbridge *mbridge)
131 {
132     return mbridge ? mbridge->has_mirrors : false;
133 }
134
135 /* Returns true if configurations changes in 'mbridge''s mirrors require
136  * revalidation, and resets the revalidation flag to false. */
137 bool
138 mbridge_need_revalidate(struct mbridge *mbridge)
139 {
140     bool need_revalidate = mbridge->need_revalidate;
141     mbridge->need_revalidate = false;
142     return need_revalidate;
143 }
144
145 void
146 mbridge_register_bundle(struct mbridge *mbridge, struct ofbundle *ofbundle)
147 {
148     struct mbundle *mbundle;
149
150     mbundle = xzalloc(sizeof *mbundle);
151     mbundle->ofbundle = ofbundle;
152     hmap_insert(&mbridge->mbundles, &mbundle->hmap_node,
153                 hash_pointer(ofbundle, 0));
154 }
155
156 void
157 mbridge_unregister_bundle(struct mbridge *mbridge, struct ofbundle *ofbundle)
158 {
159     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
160     size_t i;
161
162     if (!mbundle) {
163         return;
164     }
165
166     for (i = 0; i < MAX_MIRRORS; i++) {
167         struct mirror *m = mbridge->mirrors[i];
168         if (m) {
169             if (m->out == mbundle) {
170                 mirror_destroy(mbridge, m->aux);
171             } else if (hmapx_find_and_delete(&m->srcs, mbundle)
172                        || hmapx_find_and_delete(&m->dsts, mbundle)) {
173                 mbridge->need_revalidate = true;
174             }
175         }
176     }
177
178     hmap_remove(&mbridge->mbundles, &mbundle->hmap_node);
179     free(mbundle);
180 }
181
182 mirror_mask_t
183 mirror_bundle_out(struct mbridge *mbridge, struct ofbundle *ofbundle)
184 {
185     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
186     return mbundle ? mbundle->mirror_out : 0;
187 }
188
189 mirror_mask_t
190 mirror_bundle_src(struct mbridge *mbridge, struct ofbundle *ofbundle)
191 {
192     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
193     return mbundle ? mbundle->src_mirrors : 0;
194 }
195
196 mirror_mask_t
197 mirror_bundle_dst(struct mbridge *mbridge, struct ofbundle *ofbundle)
198 {
199     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
200     return mbundle ? mbundle->dst_mirrors : 0;
201 }
202
203 int
204 mirror_set(struct mbridge *mbridge, void *aux, const char *name,
205            struct ofbundle **srcs, size_t n_srcs,
206            struct ofbundle **dsts, size_t n_dsts,
207            unsigned long *src_vlans, struct ofbundle *out_bundle,
208            uint16_t snaplen,
209            uint16_t out_vlan)
210 {
211     struct mbundle *mbundle, *out;
212     mirror_mask_t mirror_bit;
213     struct mirror *mirror;
214     struct hmapx srcs_map;          /* Contains "struct ofbundle *"s. */
215     struct hmapx dsts_map;          /* Contains "struct ofbundle *"s. */
216
217     mirror = mirror_lookup(mbridge, aux);
218     if (!mirror) {
219         int idx;
220
221         idx = mirror_scan(mbridge);
222         if (idx < 0) {
223             VLOG_WARN("maximum of %d port mirrors reached, cannot create %s",
224                       MAX_MIRRORS, name);
225             return EFBIG;
226         }
227
228         mirror = mbridge->mirrors[idx] = xzalloc(sizeof *mirror);
229         mirror->mbridge = mbridge;
230         mirror->idx = idx;
231         mirror->aux = aux;
232         mirror->out_vlan = -1;
233         mirror->snaplen = 0;
234     }
235
236     /* Get the new configuration. */
237     if (out_bundle) {
238         out = mbundle_lookup(mbridge, out_bundle);
239         if (!out) {
240             mirror_destroy(mbridge, mirror->aux);
241             return EINVAL;
242         }
243         out_vlan = -1;
244     } else {
245         out = NULL;
246     }
247     mbundle_lookup_multiple(mbridge, srcs, n_srcs, &srcs_map);
248     mbundle_lookup_multiple(mbridge, dsts, n_dsts, &dsts_map);
249
250     /* If the configuration has not changed, do nothing. */
251     if (hmapx_equals(&srcs_map, &mirror->srcs)
252         && hmapx_equals(&dsts_map, &mirror->dsts)
253         && vlan_bitmap_equal(mirror->vlans, src_vlans)
254         && mirror->out == out
255         && mirror->out_vlan == out_vlan)
256     {
257         hmapx_destroy(&srcs_map);
258         hmapx_destroy(&dsts_map);
259         return 0;
260     }
261
262     hmapx_swap(&srcs_map, &mirror->srcs);
263     hmapx_destroy(&srcs_map);
264
265     hmapx_swap(&dsts_map, &mirror->dsts);
266     hmapx_destroy(&dsts_map);
267
268     free(mirror->vlans);
269     mirror->vlans = vlan_bitmap_clone(src_vlans);
270
271     mirror->out = out;
272     mirror->out_vlan = out_vlan;
273     mirror->snaplen = snaplen;
274
275     /* Update mbundles. */
276     mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
277     HMAP_FOR_EACH (mbundle, hmap_node, &mirror->mbridge->mbundles) {
278         if (hmapx_contains(&mirror->srcs, mbundle)) {
279             mbundle->src_mirrors |= mirror_bit;
280         } else {
281             mbundle->src_mirrors &= ~mirror_bit;
282         }
283
284         if (hmapx_contains(&mirror->dsts, mbundle)) {
285             mbundle->dst_mirrors |= mirror_bit;
286         } else {
287             mbundle->dst_mirrors &= ~mirror_bit;
288         }
289
290         if (mirror->out == mbundle) {
291             mbundle->mirror_out |= mirror_bit;
292         } else {
293             mbundle->mirror_out &= ~mirror_bit;
294         }
295     }
296
297     mbridge->has_mirrors = true;
298     mirror_update_dups(mbridge);
299
300     return 0;
301 }
302
303 void
304 mirror_destroy(struct mbridge *mbridge, void *aux)
305 {
306     struct mirror *mirror = mirror_lookup(mbridge, aux);
307     mirror_mask_t mirror_bit;
308     struct mbundle *mbundle;
309     int i;
310
311     if (!mirror) {
312         return;
313     }
314
315     mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
316     HMAP_FOR_EACH (mbundle, hmap_node, &mbridge->mbundles) {
317         mbundle->src_mirrors &= ~mirror_bit;
318         mbundle->dst_mirrors &= ~mirror_bit;
319         mbundle->mirror_out &= ~mirror_bit;
320     }
321
322     hmapx_destroy(&mirror->srcs);
323     hmapx_destroy(&mirror->dsts);
324     free(mirror->vlans);
325
326     mbridge->mirrors[mirror->idx] = NULL;
327     free(mirror);
328
329     mirror_update_dups(mbridge);
330
331     mbridge->has_mirrors = false;
332     for (i = 0; i < MAX_MIRRORS; i++) {
333         if (mbridge->mirrors[i]) {
334             mbridge->has_mirrors = true;
335             break;
336         }
337     }
338 }
339
340 int
341 mirror_get_stats(struct mbridge *mbridge, void *aux, uint64_t *packets,
342                  uint64_t *bytes)
343 {
344     struct mirror *mirror = mirror_lookup(mbridge, aux);
345
346     if (!mirror) {
347         *packets = *bytes = UINT64_MAX;
348         return 0;
349     }
350
351     *packets = mirror->packet_count;
352     *bytes = mirror->byte_count;
353
354     return 0;
355 }
356
357 void
358 mirror_update_stats(struct mbridge *mbridge, mirror_mask_t mirrors,
359                     uint64_t packets, uint64_t bytes)
360 {
361     if (!mbridge || !mirrors) {
362         return;
363     }
364
365     for (; mirrors; mirrors = zero_rightmost_1bit(mirrors)) {
366         struct mirror *m;
367
368         m = mbridge->mirrors[raw_ctz(mirrors)];
369
370         if (!m) {
371             /* In normal circumstances 'm' will not be NULL.  However,
372              * if mirrors are reconfigured, we can temporarily get out
373              * of sync in facet_revalidate().  We could "correct" the
374              * mirror list before reaching here, but doing that would
375              * not properly account the traffic stats we've currently
376              * accumulated for previous mirror configuration. */
377             continue;
378         }
379
380         m->packet_count += packets;
381         m->byte_count += bytes;
382     }
383 }
384
385 /* Retrieves the mirror numbered 'index' in 'mbridge'.  Returns true if such a
386  * mirror exists, false otherwise.
387  *
388  * If successful, '*vlans' receives the mirror's VLAN membership information,
389  * either a null pointer if the mirror includes all VLANs or a 4096-bit bitmap
390  * in which a 1-bit indicates that the mirror includes a particular VLAN,
391  * '*dup_mirrors' receives a bitmap of mirrors whose output duplicates mirror
392  * 'index', '*out' receives the output ofbundle (if any), and '*out_vlan'
393  * receives the output VLAN (if any). */
394 bool
395 mirror_get(struct mbridge *mbridge, int index, const unsigned long **vlans,
396            mirror_mask_t *dup_mirrors, struct ofbundle **out,
397            int *snaplen, int *out_vlan)
398 {
399     struct mirror *mirror;
400
401     if (!mbridge) {
402         return false;
403     }
404
405     mirror = mbridge->mirrors[index];
406     if (!mirror) {
407         return false;
408     }
409
410     *vlans = mirror->vlans;
411     *dup_mirrors = mirror->dup_mirrors;
412     *out = mirror->out ? mirror->out->ofbundle : NULL;
413     *out_vlan = mirror->out_vlan;
414     *snaplen = mirror->snaplen;
415     return true;
416 }
417 \f
418 /* Helpers. */
419
420 static struct mbundle *
421 mbundle_lookup(const struct mbridge *mbridge, struct ofbundle *ofbundle)
422 {
423     struct mbundle *mbundle;
424
425     HMAP_FOR_EACH_IN_BUCKET (mbundle, hmap_node, hash_pointer(ofbundle, 0),
426                              &mbridge->mbundles) {
427         if (mbundle->ofbundle == ofbundle) {
428             return mbundle;
429         }
430     }
431     return NULL;
432 }
433
434 /* Looks up each of the 'n_ofbundlees' pointers in 'ofbundlees' as mbundles and
435  * adds the ones that are found to 'mbundles'. */
436 static void
437 mbundle_lookup_multiple(const struct mbridge *mbridge,
438                         struct ofbundle **ofbundles, size_t n_ofbundles,
439                         struct hmapx *mbundles)
440 {
441     size_t i;
442
443     hmapx_init(mbundles);
444     for (i = 0; i < n_ofbundles; i++) {
445         struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundles[i]);
446         if (mbundle) {
447             hmapx_add(mbundles, mbundle);
448         }
449     }
450 }
451
452 static int
453 mirror_scan(struct mbridge *mbridge)
454 {
455     int idx;
456
457     for (idx = 0; idx < MAX_MIRRORS; idx++) {
458         if (!mbridge->mirrors[idx]) {
459             return idx;
460         }
461     }
462     return -1;
463 }
464
465 static struct mirror *
466 mirror_lookup(struct mbridge *mbridge, void *aux)
467 {
468     int i;
469
470     for (i = 0; i < MAX_MIRRORS; i++) {
471         struct mirror *mirror = mbridge->mirrors[i];
472         if (mirror && mirror->aux == aux) {
473             return mirror;
474         }
475     }
476
477     return NULL;
478 }
479
480 /* Update the 'dup_mirrors' member of each of the mirrors in 'ofproto'. */
481 static void
482 mirror_update_dups(struct mbridge *mbridge)
483 {
484     int i;
485
486     for (i = 0; i < MAX_MIRRORS; i++) {
487         struct mirror *m = mbridge->mirrors[i];
488
489         if (m) {
490             m->dup_mirrors = MIRROR_MASK_C(1) << i;
491         }
492     }
493
494     for (i = 0; i < MAX_MIRRORS; i++) {
495         struct mirror *m1 = mbridge->mirrors[i];
496         int j;
497
498         if (!m1) {
499             continue;
500         }
501
502         for (j = i + 1; j < MAX_MIRRORS; j++) {
503             struct mirror *m2 = mbridge->mirrors[j];
504
505             if (m2 && m1->out == m2->out && m1->out_vlan == m2->out_vlan) {
506                 m1->dup_mirrors |= MIRROR_MASK_C(1) << j;
507                 m2->dup_mirrors |= m1->dup_mirrors;
508             }
509         }
510     }
511 }