LCOV - code coverage report
Current view: top level - ofproto - ofproto-dpif-mirror.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 168 196 85.7 %
Date: 2016-09-14 01:02:56 Functions: 20 21 95.2 %
Branches: 93 130 71.5 %

           Branch data     Line data    Source code
       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 "openvswitch/hmap.h"
      22                 :            : #include "hmapx.h"
      23                 :            : #include "ofproto.h"
      24                 :            : #include "vlan-bitmap.h"
      25                 :            : #include "openvswitch/vlog.h"
      26                 :            : 
      27                 :       1288 : 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                 :        749 : mbridge_create(void)
      83                 :            : {
      84                 :            :     struct mbridge *mbridge;
      85                 :            : 
      86                 :        749 :     mbridge = xzalloc(sizeof *mbridge);
      87                 :        749 :     ovs_refcount_init(&mbridge->ref_cnt);
      88                 :            : 
      89                 :        749 :     hmap_init(&mbridge->mbundles);
      90                 :        749 :     return mbridge;
      91                 :            : }
      92                 :            : 
      93                 :            : struct mbridge *
      94                 :      41779 : mbridge_ref(const struct mbridge *mbridge_)
      95                 :            : {
      96                 :      41779 :     struct mbridge *mbridge = CONST_CAST(struct mbridge *, mbridge_);
      97         [ +  - ]:      41779 :     if (mbridge) {
      98                 :      41779 :         ovs_refcount_ref(&mbridge->ref_cnt);
      99                 :            :     }
     100                 :      41779 :     return mbridge;
     101                 :            : }
     102                 :            : 
     103                 :            : void
     104                 :      84302 : mbridge_unref(struct mbridge *mbridge)
     105                 :            : {
     106                 :            :     struct mbundle *mbundle, *next;
     107                 :            :     size_t i;
     108                 :            : 
     109         [ +  + ]:      84302 :     if (!mbridge) {
     110                 :      41774 :         return;
     111                 :            :     }
     112                 :            : 
     113         [ +  + ]:      42528 :     if (ovs_refcount_unref(&mbridge->ref_cnt) == 1) {
     114         [ +  + ]:      24717 :         for (i = 0; i < MAX_MIRRORS; i++) {
     115         [ -  + ]:      23968 :             if (mbridge->mirrors[i]) {
     116                 :          0 :                 mirror_destroy(mbridge, mbridge->mirrors[i]->aux);
     117                 :            :             }
     118                 :            :         }
     119                 :            : 
     120 [ +  - ][ -  + ]:        749 :         HMAP_FOR_EACH_SAFE (mbundle, next, hmap_node, &mbridge->mbundles) {
                 [ -  + ]
     121                 :          0 :             mbridge_unregister_bundle(mbridge, mbundle->ofbundle);
     122                 :            :         }
     123                 :            : 
     124                 :        749 :         hmap_destroy(&mbridge->mbundles);
     125                 :        749 :         free(mbridge);
     126                 :            :     }
     127                 :            : }
     128                 :            : 
     129                 :            : bool
     130                 :     173720 : mbridge_has_mirrors(struct mbridge *mbridge)
     131                 :            : {
     132 [ +  - ][ +  + ]:     173720 :     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                 :     157605 : mbridge_need_revalidate(struct mbridge *mbridge)
     139                 :            : {
     140                 :     157605 :     bool need_revalidate = mbridge->need_revalidate;
     141                 :     157605 :     mbridge->need_revalidate = false;
     142                 :     157605 :     return need_revalidate;
     143                 :            : }
     144                 :            : 
     145                 :            : void
     146                 :       2667 : mbridge_register_bundle(struct mbridge *mbridge, struct ofbundle *ofbundle)
     147                 :            : {
     148                 :            :     struct mbundle *mbundle;
     149                 :            : 
     150                 :       2667 :     mbundle = xzalloc(sizeof *mbundle);
     151                 :       2667 :     mbundle->ofbundle = ofbundle;
     152                 :       2667 :     hmap_insert(&mbridge->mbundles, &mbundle->hmap_node,
     153                 :            :                 hash_pointer(ofbundle, 0));
     154                 :       2667 : }
     155                 :            : 
     156                 :            : void
     157                 :       2667 : mbridge_unregister_bundle(struct mbridge *mbridge, struct ofbundle *ofbundle)
     158                 :            : {
     159                 :       2667 :     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
     160                 :            :     size_t i;
     161                 :            : 
     162         [ -  + ]:       2667 :     if (!mbundle) {
     163                 :          0 :         return;
     164                 :            :     }
     165                 :            : 
     166         [ +  + ]:      88011 :     for (i = 0; i < MAX_MIRRORS; i++) {
     167                 :      85344 :         struct mirror *m = mbridge->mirrors[i];
     168         [ +  + ]:      85344 :         if (m) {
     169         [ +  + ]:         54 :             if (m->out == mbundle) {
     170                 :         16 :                 mirror_destroy(mbridge, m->aux);
     171         [ +  + ]:         38 :             } else if (hmapx_find_and_delete(&m->srcs, mbundle)
     172         [ +  + ]:          7 :                        || hmapx_find_and_delete(&m->dsts, mbundle)) {
     173                 :         35 :                 mbridge->need_revalidate = true;
     174                 :            :             }
     175                 :            :         }
     176                 :            :     }
     177                 :            : 
     178                 :       2667 :     hmap_remove(&mbridge->mbundles, &mbundle->hmap_node);
     179                 :       2667 :     free(mbundle);
     180                 :            : }
     181                 :            : 
     182                 :            : mirror_mask_t
     183                 :     148933 : mirror_bundle_out(struct mbridge *mbridge, struct ofbundle *ofbundle)
     184                 :            : {
     185                 :     148933 :     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
     186         [ +  - ]:     148933 :     return mbundle ? mbundle->mirror_out : 0;
     187                 :            : }
     188                 :            : 
     189                 :            : mirror_mask_t
     190                 :         55 : mirror_bundle_src(struct mbridge *mbridge, struct ofbundle *ofbundle)
     191                 :            : {
     192                 :         55 :     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
     193         [ +  - ]:         55 :     return mbundle ? mbundle->src_mirrors : 0;
     194                 :            : }
     195                 :            : 
     196                 :            : mirror_mask_t
     197                 :        101 : mirror_bundle_dst(struct mbridge *mbridge, struct ofbundle *ofbundle)
     198                 :            : {
     199                 :        101 :     struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundle);
     200         [ +  - ]:        101 :     return mbundle ? mbundle->dst_mirrors : 0;
     201                 :            : }
     202                 :            : 
     203                 :            : int
     204                 :         22 : 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                 :         22 :     mirror = mirror_lookup(mbridge, aux);
     218         [ +  - ]:         22 :     if (!mirror) {
     219                 :            :         int idx;
     220                 :            : 
     221                 :         22 :         idx = mirror_scan(mbridge);
     222         [ -  + ]:         22 :         if (idx < 0) {
     223         [ #  # ]:          0 :             VLOG_WARN("maximum of %d port mirrors reached, cannot create %s",
     224                 :            :                       MAX_MIRRORS, name);
     225                 :          0 :             return EFBIG;
     226                 :            :         }
     227                 :            : 
     228                 :         22 :         mirror = mbridge->mirrors[idx] = xzalloc(sizeof *mirror);
     229                 :         22 :         mirror->mbridge = mbridge;
     230                 :         22 :         mirror->idx = idx;
     231                 :         22 :         mirror->aux = aux;
     232                 :         22 :         mirror->out_vlan = -1;
     233                 :         22 :         mirror->snaplen = 0;
     234                 :            :     }
     235                 :            : 
     236                 :            :     /* Get the new configuration. */
     237         [ +  + ]:         22 :     if (out_bundle) {
     238                 :         16 :         out = mbundle_lookup(mbridge, out_bundle);
     239         [ -  + ]:         16 :         if (!out) {
     240                 :          0 :             mirror_destroy(mbridge, mirror->aux);
     241                 :          0 :             return EINVAL;
     242                 :            :         }
     243                 :         16 :         out_vlan = -1;
     244                 :            :     } else {
     245                 :          6 :         out = NULL;
     246                 :            :     }
     247                 :         22 :     mbundle_lookup_multiple(mbridge, srcs, n_srcs, &srcs_map);
     248                 :         22 :     mbundle_lookup_multiple(mbridge, dsts, n_dsts, &dsts_map);
     249                 :            : 
     250                 :            :     /* If the configuration has not changed, do nothing. */
     251         [ +  + ]:         22 :     if (hmapx_equals(&srcs_map, &mirror->srcs)
     252         [ -  + ]:          3 :         && hmapx_equals(&dsts_map, &mirror->dsts)
     253         [ #  # ]:          0 :         && vlan_bitmap_equal(mirror->vlans, src_vlans)
     254         [ #  # ]:          0 :         && mirror->out == out
     255         [ #  # ]:          0 :         && mirror->out_vlan == out_vlan)
     256                 :            :     {
     257                 :          0 :         hmapx_destroy(&srcs_map);
     258                 :          0 :         hmapx_destroy(&dsts_map);
     259                 :          0 :         return 0;
     260                 :            :     }
     261                 :            : 
     262                 :         22 :     hmapx_swap(&srcs_map, &mirror->srcs);
     263                 :         22 :     hmapx_destroy(&srcs_map);
     264                 :            : 
     265                 :         22 :     hmapx_swap(&dsts_map, &mirror->dsts);
     266                 :         22 :     hmapx_destroy(&dsts_map);
     267                 :            : 
     268                 :         22 :     free(mirror->vlans);
     269                 :         22 :     mirror->vlans = vlan_bitmap_clone(src_vlans);
     270                 :            : 
     271                 :         22 :     mirror->out = out;
     272                 :         22 :     mirror->out_vlan = out_vlan;
     273                 :         22 :     mirror->snaplen = snaplen;
     274                 :            : 
     275                 :            :     /* Update mbundles. */
     276                 :         22 :     mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
     277 [ +  + ][ -  + ]:        109 :     HMAP_FOR_EACH (mbundle, hmap_node, &mirror->mbridge->mbundles) {
     278         [ +  + ]:         87 :         if (hmapx_contains(&mirror->srcs, mbundle)) {
     279                 :         67 :             mbundle->src_mirrors |= mirror_bit;
     280                 :            :         } else {
     281                 :         20 :             mbundle->src_mirrors &= ~mirror_bit;
     282                 :            :         }
     283                 :            : 
     284         [ +  + ]:         87 :         if (hmapx_contains(&mirror->dsts, mbundle)) {
     285                 :         70 :             mbundle->dst_mirrors |= mirror_bit;
     286                 :            :         } else {
     287                 :         17 :             mbundle->dst_mirrors &= ~mirror_bit;
     288                 :            :         }
     289                 :            : 
     290         [ +  + ]:         87 :         if (mirror->out == mbundle) {
     291                 :         16 :             mbundle->mirror_out |= mirror_bit;
     292                 :            :         } else {
     293                 :         71 :             mbundle->mirror_out &= ~mirror_bit;
     294                 :            :         }
     295                 :            :     }
     296                 :            : 
     297                 :         22 :     mbridge->has_mirrors = true;
     298                 :         22 :     mirror_update_dups(mbridge);
     299                 :            : 
     300                 :         22 :     return 0;
     301                 :            : }
     302                 :            : 
     303                 :            : void
     304                 :         38 : mirror_destroy(struct mbridge *mbridge, void *aux)
     305                 :            : {
     306                 :         38 :     struct mirror *mirror = mirror_lookup(mbridge, aux);
     307                 :            :     mirror_mask_t mirror_bit;
     308                 :            :     struct mbundle *mbundle;
     309                 :            :     int i;
     310                 :            : 
     311         [ +  + ]:         38 :     if (!mirror) {
     312                 :         16 :         return;
     313                 :            :     }
     314                 :            : 
     315                 :         22 :     mirror_bit = MIRROR_MASK_C(1) << mirror->idx;
     316 [ +  + ][ -  + ]:         71 :     HMAP_FOR_EACH (mbundle, hmap_node, &mbridge->mbundles) {
     317                 :         49 :         mbundle->src_mirrors &= ~mirror_bit;
     318                 :         49 :         mbundle->dst_mirrors &= ~mirror_bit;
     319                 :         49 :         mbundle->mirror_out &= ~mirror_bit;
     320                 :            :     }
     321                 :            : 
     322                 :         22 :     hmapx_destroy(&mirror->srcs);
     323                 :         22 :     hmapx_destroy(&mirror->dsts);
     324                 :         22 :     free(mirror->vlans);
     325                 :            : 
     326                 :         22 :     mbridge->mirrors[mirror->idx] = NULL;
     327                 :         22 :     free(mirror);
     328                 :            : 
     329                 :         22 :     mirror_update_dups(mbridge);
     330                 :            : 
     331                 :         22 :     mbridge->has_mirrors = false;
     332         [ +  + ]:        663 :     for (i = 0; i < MAX_MIRRORS; i++) {
     333         [ +  + ]:        643 :         if (mbridge->mirrors[i]) {
     334                 :          2 :             mbridge->has_mirrors = true;
     335                 :          2 :             break;
     336                 :            :         }
     337                 :            :     }
     338                 :            : }
     339                 :            : 
     340                 :            : int
     341                 :          0 : mirror_get_stats(struct mbridge *mbridge, void *aux, uint64_t *packets,
     342                 :            :                  uint64_t *bytes)
     343                 :            : {
     344                 :          0 :     struct mirror *mirror = mirror_lookup(mbridge, aux);
     345                 :            : 
     346         [ #  # ]:          0 :     if (!mirror) {
     347                 :          0 :         *packets = *bytes = UINT64_MAX;
     348                 :          0 :         return 0;
     349                 :            :     }
     350                 :            : 
     351                 :          0 :     *packets = mirror->packet_count;
     352                 :          0 :     *bytes = mirror->byte_count;
     353                 :            : 
     354                 :          0 :     return 0;
     355                 :            : }
     356                 :            : 
     357                 :            : void
     358                 :          6 : mirror_update_stats(struct mbridge *mbridge, mirror_mask_t mirrors,
     359                 :            :                     uint64_t packets, uint64_t bytes)
     360                 :            : {
     361 [ +  - ][ -  + ]:          6 :     if (!mbridge || !mirrors) {
     362                 :          0 :         return;
     363                 :            :     }
     364                 :            : 
     365         [ +  + ]:         12 :     for (; mirrors; mirrors = zero_rightmost_1bit(mirrors)) {
     366                 :            :         struct mirror *m;
     367                 :            : 
     368                 :          6 :         m = mbridge->mirrors[raw_ctz(mirrors)];
     369                 :            : 
     370         [ +  + ]:          6 :         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                 :          1 :             continue;
     378                 :            :         }
     379                 :            : 
     380                 :          5 :         m->packet_count += packets;
     381                 :          5 :         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                 :         46 : 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         [ -  + ]:         46 :     if (!mbridge) {
     402                 :          0 :         return false;
     403                 :            :     }
     404                 :            : 
     405                 :         46 :     mirror = mbridge->mirrors[index];
     406         [ -  + ]:         46 :     if (!mirror) {
     407                 :          0 :         return false;
     408                 :            :     }
     409                 :            : 
     410                 :         46 :     *vlans = mirror->vlans;
     411                 :         46 :     *dup_mirrors = mirror->dup_mirrors;
     412         [ +  + ]:         46 :     *out = mirror->out ? mirror->out->ofbundle : NULL;
     413                 :         46 :     *out_vlan = mirror->out_vlan;
     414                 :         46 :     *snaplen = mirror->snaplen;
     415                 :         46 :     return true;
     416                 :            : }
     417                 :            : 
     418                 :            : /* Helpers. */
     419                 :            : 
     420                 :            : static struct mbundle *
     421                 :     151909 : mbundle_lookup(const struct mbridge *mbridge, struct ofbundle *ofbundle)
     422                 :            : {
     423                 :            :     struct mbundle *mbundle;
     424                 :            : 
     425 [ +  - ][ #  # ]:     174537 :     HMAP_FOR_EACH_IN_BUCKET (mbundle, hmap_node, hash_pointer(ofbundle, 0),
     426                 :            :                              &mbridge->mbundles) {
     427         [ +  + ]:     174537 :         if (mbundle->ofbundle == ofbundle) {
     428                 :     151909 :             return mbundle;
     429                 :            :         }
     430                 :            :     }
     431                 :          0 :     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                 :         44 : 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                 :         44 :     hmapx_init(mbundles);
     444         [ +  + ]:        181 :     for (i = 0; i < n_ofbundles; i++) {
     445                 :        137 :         struct mbundle *mbundle = mbundle_lookup(mbridge, ofbundles[i]);
     446         [ +  - ]:        137 :         if (mbundle) {
     447                 :        137 :             hmapx_add(mbundles, mbundle);
     448                 :            :         }
     449                 :            :     }
     450                 :         44 : }
     451                 :            : 
     452                 :            : static int
     453                 :         22 : mirror_scan(struct mbridge *mbridge)
     454                 :            : {
     455                 :            :     int idx;
     456                 :            : 
     457         [ +  - ]:         24 :     for (idx = 0; idx < MAX_MIRRORS; idx++) {
     458         [ +  + ]:         24 :         if (!mbridge->mirrors[idx]) {
     459                 :         22 :             return idx;
     460                 :            :         }
     461                 :            :     }
     462                 :          0 :     return -1;
     463                 :            : }
     464                 :            : 
     465                 :            : static struct mirror *
     466                 :         60 : mirror_lookup(struct mbridge *mbridge, void *aux)
     467                 :            : {
     468                 :            :     int i;
     469                 :            : 
     470         [ +  + ]:       1278 :     for (i = 0; i < MAX_MIRRORS; i++) {
     471                 :       1240 :         struct mirror *mirror = mbridge->mirrors[i];
     472 [ +  + ][ +  + ]:       1240 :         if (mirror && mirror->aux == aux) {
     473                 :         22 :             return mirror;
     474                 :            :         }
     475                 :            :     }
     476                 :            : 
     477                 :         38 :     return NULL;
     478                 :            : }
     479                 :            : 
     480                 :            : /* Update the 'dup_mirrors' member of each of the mirrors in 'ofproto'. */
     481                 :            : static void
     482                 :         44 : mirror_update_dups(struct mbridge *mbridge)
     483                 :            : {
     484                 :            :     int i;
     485                 :            : 
     486         [ +  + ]:       1452 :     for (i = 0; i < MAX_MIRRORS; i++) {
     487                 :       1408 :         struct mirror *m = mbridge->mirrors[i];
     488                 :            : 
     489         [ +  + ]:       1408 :         if (m) {
     490                 :         26 :             m->dup_mirrors = MIRROR_MASK_C(1) << i;
     491                 :            :         }
     492                 :            :     }
     493                 :            : 
     494         [ +  + ]:       1452 :     for (i = 0; i < MAX_MIRRORS; i++) {
     495                 :       1408 :         struct mirror *m1 = mbridge->mirrors[i];
     496                 :            :         int j;
     497                 :            : 
     498         [ +  + ]:       1408 :         if (!m1) {
     499                 :       1382 :             continue;
     500                 :            :         }
     501                 :            : 
     502         [ +  + ]:        829 :         for (j = i + 1; j < MAX_MIRRORS; j++) {
     503                 :        803 :             struct mirror *m2 = mbridge->mirrors[j];
     504                 :            : 
     505 [ +  + ][ +  - ]:        803 :             if (m2 && m1->out == m2->out && m1->out_vlan == m2->out_vlan) {
                 [ -  + ]
     506                 :          0 :                 m1->dup_mirrors |= MIRROR_MASK_C(1) << j;
     507                 :          0 :                 m2->dup_mirrors |= m1->dup_mirrors;
     508                 :            :             }
     509                 :            :         }
     510                 :            :     }
     511                 :         44 : }

Generated by: LCOV version 1.12