LCOV - code coverage report
Current view: top level - lib - netdev-dummy.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 696 793 87.8 %
Date: 2016-09-14 01:02:56 Functions: 68 69 98.6 %
Branches: 213 299 71.2 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2010, 2011, 2012, 2013, 2015, 2016 Nicira, Inc.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at:
       7                 :            :  *
       8                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include <config.h>
      18                 :            : 
      19                 :            : #include "dummy.h"
      20                 :            : 
      21                 :            : #include <errno.h>
      22                 :            : #include <unistd.h>
      23                 :            : 
      24                 :            : #include "dp-packet.h"
      25                 :            : #include "dpif-netdev.h"
      26                 :            : #include "flow.h"
      27                 :            : #include "netdev-provider.h"
      28                 :            : #include "netdev-vport.h"
      29                 :            : #include "odp-util.h"
      30                 :            : #include "openvswitch/dynamic-string.h"
      31                 :            : #include "openvswitch/list.h"
      32                 :            : #include "openvswitch/ofp-print.h"
      33                 :            : #include "openvswitch/ofpbuf.h"
      34                 :            : #include "openvswitch/vlog.h"
      35                 :            : #include "ovs-atomic.h"
      36                 :            : #include "packets.h"
      37                 :            : #include "pcap-file.h"
      38                 :            : #include "poll-loop.h"
      39                 :            : #include "openvswitch/shash.h"
      40                 :            : #include "sset.h"
      41                 :            : #include "stream.h"
      42                 :            : #include "unaligned.h"
      43                 :            : #include "timeval.h"
      44                 :            : #include "unixctl.h"
      45                 :            : #include "reconnect.h"
      46                 :            : 
      47                 :       1288 : VLOG_DEFINE_THIS_MODULE(netdev_dummy);
      48                 :            : 
      49                 :            : struct reconnect;
      50                 :            : 
      51                 :            : struct dummy_packet_stream {
      52                 :            :     struct stream *stream;
      53                 :            :     struct dp_packet rxbuf;
      54                 :            :     struct ovs_list txq;
      55                 :            : };
      56                 :            : 
      57                 :            : enum dummy_packet_conn_type {
      58                 :            :     NONE,       /* No connection is configured. */
      59                 :            :     PASSIVE,    /* Listener. */
      60                 :            :     ACTIVE      /* Connect to listener. */
      61                 :            : };
      62                 :            : 
      63                 :            : enum dummy_netdev_conn_state {
      64                 :            :     CONN_STATE_CONNECTED,      /* Listener connected. */
      65                 :            :     CONN_STATE_NOT_CONNECTED,  /* Listener not connected.  */
      66                 :            :     CONN_STATE_UNKNOWN,        /* No relavent information.  */
      67                 :            : };
      68                 :            : 
      69                 :            : struct dummy_packet_pconn {
      70                 :            :     struct pstream *pstream;
      71                 :            :     struct dummy_packet_stream **streams;
      72                 :            :     size_t n_streams;
      73                 :            : };
      74                 :            : 
      75                 :            : struct dummy_packet_rconn {
      76                 :            :     struct dummy_packet_stream *rstream;
      77                 :            :     struct reconnect *reconnect;
      78                 :            : };
      79                 :            : 
      80                 :            : struct dummy_packet_conn {
      81                 :            :     enum dummy_packet_conn_type type;
      82                 :            :     union {
      83                 :            :         struct dummy_packet_pconn pconn;
      84                 :            :         struct dummy_packet_rconn rconn;
      85                 :            :     } u;
      86                 :            : };
      87                 :            : 
      88                 :            : struct pkt_list_node {
      89                 :            :     struct dp_packet *pkt;
      90                 :            :     struct ovs_list list_node;
      91                 :            : };
      92                 :            : 
      93                 :            : /* Protects 'dummy_list'. */
      94                 :            : static struct ovs_mutex dummy_list_mutex = OVS_MUTEX_INITIALIZER;
      95                 :            : 
      96                 :            : /* Contains all 'struct dummy_dev's. */
      97                 :            : static struct ovs_list dummy_list OVS_GUARDED_BY(dummy_list_mutex)
      98                 :            :     = OVS_LIST_INITIALIZER(&dummy_list);
      99                 :            : 
     100                 :            : struct netdev_dummy {
     101                 :            :     struct netdev up;
     102                 :            : 
     103                 :            :     /* In dummy_list. */
     104                 :            :     struct ovs_list list_node OVS_GUARDED_BY(dummy_list_mutex);
     105                 :            : 
     106                 :            :     /* Protects all members below. */
     107                 :            :     struct ovs_mutex mutex OVS_ACQ_AFTER(dummy_list_mutex);
     108                 :            : 
     109                 :            :     struct eth_addr hwaddr OVS_GUARDED;
     110                 :            :     int mtu OVS_GUARDED;
     111                 :            :     struct netdev_stats stats OVS_GUARDED;
     112                 :            :     enum netdev_flags flags OVS_GUARDED;
     113                 :            :     int ifindex OVS_GUARDED;
     114                 :            :     int numa_id OVS_GUARDED;
     115                 :            : 
     116                 :            :     struct dummy_packet_conn conn OVS_GUARDED;
     117                 :            : 
     118                 :            :     FILE *tx_pcap, *rxq_pcap OVS_GUARDED;
     119                 :            : 
     120                 :            :     struct in_addr address, netmask;
     121                 :            :     struct in6_addr ipv6, ipv6_mask;
     122                 :            :     struct ovs_list rxes OVS_GUARDED; /* List of child "netdev_rxq_dummy"s. */
     123                 :            : 
     124                 :            :     /* The following properties are for dummy-pmd and they cannot be changed
     125                 :            :      * when a device is running, so we remember the request and update them
     126                 :            :      * next time netdev_dummy_reconfigure() is called. */
     127                 :            :     int requested_n_txq OVS_GUARDED;
     128                 :            :     int requested_n_rxq OVS_GUARDED;
     129                 :            :     int requested_numa_id OVS_GUARDED;
     130                 :            : };
     131                 :            : 
     132                 :            : /* Max 'recv_queue_len' in struct netdev_dummy. */
     133                 :            : #define NETDEV_DUMMY_MAX_QUEUE 100
     134                 :            : 
     135                 :            : struct netdev_rxq_dummy {
     136                 :            :     struct netdev_rxq up;
     137                 :            :     struct ovs_list node;       /* In netdev_dummy's "rxes" list. */
     138                 :            :     struct ovs_list recv_queue;
     139                 :            :     int recv_queue_len;         /* ovs_list_size(&recv_queue). */
     140                 :            :     struct seq *seq;            /* Reports newly queued packets. */
     141                 :            : };
     142                 :            : 
     143                 :            : static unixctl_cb_func netdev_dummy_set_admin_state;
     144                 :            : static int netdev_dummy_construct(struct netdev *);
     145                 :            : static void netdev_dummy_queue_packet(struct netdev_dummy *,
     146                 :            :                                       struct dp_packet *, int);
     147                 :            : 
     148                 :            : static void dummy_packet_stream_close(struct dummy_packet_stream *);
     149                 :            : 
     150                 :            : static void pkt_list_delete(struct ovs_list *);
     151                 :            : 
     152                 :            : static bool
     153                 :   53752933 : is_dummy_class(const struct netdev_class *class)
     154                 :            : {
     155                 :   53752933 :     return class->construct == netdev_dummy_construct;
     156                 :            : }
     157                 :            : 
     158                 :            : static struct netdev_dummy *
     159                 :   26959168 : netdev_dummy_cast(const struct netdev *netdev)
     160                 :            : {
     161         [ -  + ]:   26959168 :     ovs_assert(is_dummy_class(netdev_get_class(netdev)));
     162                 :   26959196 :     return CONTAINER_OF(netdev, struct netdev_dummy, up);
     163                 :            : }
     164                 :            : 
     165                 :            : static struct netdev_rxq_dummy *
     166                 :   26828802 : netdev_rxq_dummy_cast(const struct netdev_rxq *rx)
     167                 :            : {
     168         [ -  + ]:   26828802 :     ovs_assert(is_dummy_class(netdev_get_class(rx->netdev)));
     169                 :   20357388 :     return CONTAINER_OF(rx, struct netdev_rxq_dummy, up);
     170                 :            : }
     171                 :            : 
     172                 :            : static void
     173                 :        120 : dummy_packet_stream_init(struct dummy_packet_stream *s, struct stream *stream)
     174                 :            : {
     175         [ +  - ]:        120 :     int rxbuf_size = stream ? 2048 : 0;
     176                 :        120 :     s->stream = stream;
     177                 :        120 :     dp_packet_init(&s->rxbuf, rxbuf_size);
     178                 :        120 :     ovs_list_init(&s->txq);
     179                 :        120 : }
     180                 :            : 
     181                 :            : static struct dummy_packet_stream *
     182                 :         60 : dummy_packet_stream_create(struct stream *stream)
     183                 :            : {
     184                 :            :     struct dummy_packet_stream *s;
     185                 :            : 
     186                 :         60 :     s = xzalloc(sizeof *s);
     187                 :         60 :     dummy_packet_stream_init(s, stream);
     188                 :            : 
     189                 :         60 :     return s;
     190                 :            : }
     191                 :            : 
     192                 :            : static void
     193                 :      62358 : dummy_packet_stream_wait(struct dummy_packet_stream *s)
     194                 :            : {
     195                 :      62358 :     stream_run_wait(s->stream);
     196         [ +  + ]:      62358 :     if (!ovs_list_is_empty(&s->txq)) {
     197                 :       2622 :         stream_send_wait(s->stream);
     198                 :            :     }
     199                 :      62358 :     stream_recv_wait(s->stream);
     200                 :      62358 : }
     201                 :            : 
     202                 :            : static void
     203                 :       4722 : dummy_packet_stream_send(struct dummy_packet_stream *s, const void *buffer, size_t size)
     204                 :            : {
     205         [ +  - ]:       4722 :     if (ovs_list_size(&s->txq) < NETDEV_DUMMY_MAX_QUEUE) {
     206                 :            :         struct dp_packet *b;
     207                 :            :         struct pkt_list_node *node;
     208                 :            : 
     209                 :       4722 :         b = dp_packet_clone_data_with_headroom(buffer, size, 2);
     210                 :       4722 :         put_unaligned_be16(dp_packet_push_uninit(b, 2), htons(size));
     211                 :            : 
     212                 :       4722 :         node = xmalloc(sizeof *node);
     213                 :       4722 :         node->pkt = b;
     214                 :       4722 :         ovs_list_push_back(&s->txq, &node->list_node);
     215                 :            :     }
     216                 :       4722 : }
     217                 :            : 
     218                 :            : static int
     219                 :      60283 : dummy_packet_stream_run(struct netdev_dummy *dev, struct dummy_packet_stream *s)
     220                 :            : {
     221                 :      60283 :     int error = 0;
     222                 :            :     size_t n;
     223                 :            : 
     224                 :      60283 :     stream_run(s->stream);
     225                 :            : 
     226         [ +  + ]:      60283 :     if (!ovs_list_is_empty(&s->txq)) {
     227                 :            :         struct pkt_list_node *txbuf_node;
     228                 :            :         struct dp_packet *txbuf;
     229                 :            :         int retval;
     230                 :            : 
     231                 :       4722 :         ASSIGN_CONTAINER(txbuf_node, ovs_list_front(&s->txq), list_node);
     232                 :       4722 :         txbuf = txbuf_node->pkt;
     233                 :       4722 :         retval = stream_send(s->stream, dp_packet_data(txbuf), dp_packet_size(txbuf));
     234                 :            : 
     235         [ +  - ]:       4722 :         if (retval > 0) {
     236                 :       4722 :             dp_packet_pull(txbuf, retval);
     237         [ +  - ]:       4722 :             if (!dp_packet_size(txbuf)) {
     238                 :       4722 :                 ovs_list_remove(&txbuf_node->list_node);
     239                 :       4722 :                 free(txbuf_node);
     240                 :       4722 :                 dp_packet_delete(txbuf);
     241                 :            :             }
     242         [ #  # ]:          0 :         } else if (retval != -EAGAIN) {
     243                 :          0 :             error = -retval;
     244                 :            :         }
     245                 :            :     }
     246                 :            : 
     247         [ +  - ]:      60283 :     if (!error) {
     248         [ +  + ]:      60283 :         if (dp_packet_size(&s->rxbuf) < 2) {
     249                 :      55561 :             n = 2 - dp_packet_size(&s->rxbuf);
     250                 :            :         } else {
     251                 :            :             uint16_t frame_len;
     252                 :            : 
     253                 :       4722 :             frame_len = ntohs(get_unaligned_be16(dp_packet_data(&s->rxbuf)));
     254         [ -  + ]:       4722 :             if (frame_len < ETH_HEADER_LEN) {
     255                 :          0 :                 error = EPROTO;
     256                 :          0 :                 n = 0;
     257                 :            :             } else {
     258                 :       4722 :                 n = (2 + frame_len) - dp_packet_size(&s->rxbuf);
     259                 :            :             }
     260                 :            :         }
     261                 :            :     }
     262         [ +  - ]:      60283 :     if (!error) {
     263                 :            :         int retval;
     264                 :            : 
     265                 :      60283 :         dp_packet_prealloc_tailroom(&s->rxbuf, n);
     266                 :      60283 :         retval = stream_recv(s->stream, dp_packet_tail(&s->rxbuf), n);
     267                 :            : 
     268         [ +  + ]:      60283 :         if (retval > 0) {
     269                 :       9444 :             dp_packet_set_size(&s->rxbuf, dp_packet_size(&s->rxbuf) + retval);
     270 [ +  - ][ +  + ]:       9444 :             if (retval == n && dp_packet_size(&s->rxbuf) > 2) {
     271                 :       4722 :                 dp_packet_pull(&s->rxbuf, 2);
     272                 :       4722 :                 netdev_dummy_queue_packet(dev,
     273                 :       4722 :                                           dp_packet_clone(&s->rxbuf), 0);
     274                 :       9444 :                 dp_packet_clear(&s->rxbuf);
     275                 :            :             }
     276         [ +  + ]:      50839 :         } else if (retval != -EAGAIN) {
     277                 :         45 :             error = (retval < 0 ? -retval
     278         [ -  + ]:         90 :                      : dp_packet_size(&s->rxbuf) ? EPROTO
     279         [ -  + ]:         45 :                      : EOF);
     280                 :            :         }
     281                 :            :     }
     282                 :            : 
     283                 :      60283 :     return error;
     284                 :            : }
     285                 :            : 
     286                 :            : static void
     287                 :         45 : dummy_packet_stream_close(struct dummy_packet_stream *s)
     288                 :            : {
     289                 :         45 :     stream_close(s->stream);
     290                 :         45 :     dp_packet_uninit(&s->rxbuf);
     291                 :         45 :     pkt_list_delete(&s->txq);
     292                 :         45 : }
     293                 :            : 
     294                 :            : static void
     295                 :       2963 : dummy_packet_conn_init(struct dummy_packet_conn *conn)
     296                 :            : {
     297                 :       2963 :     memset(conn, 0, sizeof *conn);
     298                 :       2963 :     conn->type = NONE;
     299                 :       2963 : }
     300                 :            : 
     301                 :            : static void
     302                 :         80 : dummy_packet_conn_get_config(struct dummy_packet_conn *conn, struct smap *args)
     303                 :            : {
     304                 :            : 
     305      [ -  -  + ]:         80 :     switch (conn->type) {
     306                 :            :     case PASSIVE:
     307                 :          0 :         smap_add(args, "pstream", pstream_get_name(conn->u.pconn.pstream));
     308                 :          0 :         break;
     309                 :            : 
     310                 :            :     case ACTIVE:
     311                 :          0 :         smap_add(args, "stream", stream_get_name(conn->u.rconn.rstream->stream));
     312                 :          0 :         break;
     313                 :            : 
     314                 :            :     case NONE:
     315                 :            :     default:
     316                 :         80 :         break;
     317                 :            :     }
     318                 :         80 : }
     319                 :            : 
     320                 :            : static void
     321                 :       1038 : dummy_packet_conn_close(struct dummy_packet_conn *conn)
     322                 :            : {
     323                 :            :     int i;
     324                 :       1038 :     struct dummy_packet_pconn *pconn = &conn->u.pconn;
     325                 :       1038 :     struct dummy_packet_rconn *rconn = &conn->u.rconn;
     326                 :            : 
     327      [ +  +  + ]:       1038 :     switch (conn->type) {
     328                 :            :     case PASSIVE:
     329                 :          1 :         pstream_close(pconn->pstream);
     330         [ -  + ]:          1 :         for (i = 0; i < pconn->n_streams; i++) {
     331                 :          0 :             dummy_packet_stream_close(pconn->streams[i]);
     332                 :          0 :             free(pconn->streams[i]);
     333                 :            :         }
     334                 :          1 :         free(pconn->streams);
     335                 :          1 :         pconn->pstream = NULL;
     336                 :          1 :         pconn->streams = NULL;
     337                 :          1 :         break;
     338                 :            : 
     339                 :            :     case ACTIVE:
     340                 :          1 :         dummy_packet_stream_close(rconn->rstream);
     341                 :          1 :         free(rconn->rstream);
     342                 :          1 :         rconn->rstream = NULL;
     343                 :          1 :         reconnect_destroy(rconn->reconnect);
     344                 :          1 :         rconn->reconnect = NULL;
     345                 :          1 :         break;
     346                 :            : 
     347                 :            :     case NONE:
     348                 :            :     default:
     349                 :       1036 :         break;
     350                 :            :     }
     351                 :            : 
     352                 :       1038 :     conn->type = NONE;
     353                 :       1038 :     memset(conn, 0, sizeof *conn);
     354                 :       1038 : }
     355                 :            : 
     356                 :            : static void
     357                 :       5296 : dummy_packet_conn_set_config(struct dummy_packet_conn *conn,
     358                 :            :                              const struct smap *args)
     359                 :            : {
     360                 :       5296 :     const char *pstream = smap_get(args, "pstream");
     361                 :       5296 :     const char *stream = smap_get(args, "stream");
     362                 :            : 
     363 [ +  + ][ -  + ]:       5296 :     if (pstream && stream) {
     364         [ #  # ]:          0 :          VLOG_WARN("Open failed: both %s and %s are configured",
     365                 :            :                    pstream, stream);
     366                 :          0 :          return;
     367                 :            :     }
     368                 :            : 
     369      [ +  +  + ]:       5296 :     switch (conn->type) {
     370                 :            :     case PASSIVE:
     371   [ +  -  +  - ]:         76 :         if (pstream &&
     372                 :         38 :             !strcmp(pstream_get_name(conn->u.pconn.pstream), pstream)) {
     373                 :         38 :             return;
     374                 :            :         }
     375                 :          0 :         dummy_packet_conn_close(conn);
     376                 :          0 :         break;
     377                 :            :     case ACTIVE:
     378   [ +  -  +  - ]:        676 :         if (stream &&
     379                 :        338 :             !strcmp(stream_get_name(conn->u.rconn.rstream->stream), stream)) {
     380                 :        338 :             return;
     381                 :            :         }
     382                 :          0 :         dummy_packet_conn_close(conn);
     383                 :          0 :         break;
     384                 :            :     case NONE:
     385                 :            :     default:
     386                 :       4920 :         break;
     387                 :            :     }
     388                 :            : 
     389         [ +  + ]:       4920 :     if (pstream) {
     390                 :            :         int error;
     391                 :            : 
     392                 :         62 :         error = pstream_open(pstream, &conn->u.pconn.pstream, DSCP_DEFAULT);
     393         [ -  + ]:         62 :         if (error) {
     394         [ #  # ]:          0 :             VLOG_WARN("%s: open failed (%s)", pstream, ovs_strerror(error));
     395                 :            :         } else {
     396                 :         62 :             conn->type = PASSIVE;
     397                 :            :         }
     398                 :            :     }
     399                 :            : 
     400         [ +  + ]:       4920 :     if (stream) {
     401                 :            :         int error;
     402                 :            :         struct stream *active_stream;
     403                 :            :         struct reconnect *reconnect;
     404                 :            : 
     405                 :         60 :         reconnect = reconnect_create(time_msec());
     406                 :         60 :         reconnect_set_name(reconnect, stream);
     407                 :         60 :         reconnect_set_passive(reconnect, false, time_msec());
     408                 :         60 :         reconnect_enable(reconnect, time_msec());
     409                 :         60 :         reconnect_set_backoff(reconnect, 100, INT_MAX);
     410                 :         60 :         reconnect_set_probe_interval(reconnect, 0);
     411                 :         60 :         conn->u.rconn.reconnect = reconnect;
     412                 :         60 :         conn->type = ACTIVE;
     413                 :            : 
     414                 :         60 :         error = stream_open(stream, &active_stream, DSCP_DEFAULT);
     415                 :         60 :         conn->u.rconn.rstream = dummy_packet_stream_create(active_stream);
     416                 :            : 
     417      [ +  -  - ]:         60 :         switch (error) {
     418                 :            :         case 0:
     419                 :         60 :             reconnect_connected(reconnect, time_msec());
     420                 :         60 :             break;
     421                 :            : 
     422                 :            :         case EAGAIN:
     423                 :          0 :             reconnect_connecting(reconnect, time_msec());
     424                 :          0 :             break;
     425                 :            : 
     426                 :            :         default:
     427                 :          0 :             reconnect_connect_failed(reconnect, time_msec(), error);
     428                 :          0 :             stream_close(active_stream);
     429                 :          0 :             conn->u.rconn.rstream->stream = NULL;
     430                 :         60 :             break;
     431                 :            :         }
     432                 :            :     }
     433                 :            : }
     434                 :            : 
     435                 :            : static void
     436                 :      26703 : dummy_pconn_run(struct netdev_dummy *dev)
     437                 :            :     OVS_REQUIRES(dev->mutex)
     438                 :            : {
     439                 :            :     struct stream *new_stream;
     440                 :      26703 :     struct dummy_packet_pconn *pconn = &dev->conn.u.pconn;
     441                 :            :     int error;
     442                 :            :     size_t i;
     443                 :            : 
     444                 :      26703 :     error = pstream_accept(pconn->pstream, &new_stream);
     445         [ +  + ]:      26703 :     if (!error) {
     446                 :            :         struct dummy_packet_stream *s;
     447                 :            : 
     448                 :         60 :         pconn->streams = xrealloc(pconn->streams,
     449                 :         60 :                                 ((pconn->n_streams + 1)
     450                 :            :                                  * sizeof s));
     451                 :         60 :         s = xmalloc(sizeof *s);
     452                 :         60 :         pconn->streams[pconn->n_streams++] = s;
     453                 :         60 :         dummy_packet_stream_init(s, new_stream);
     454         [ -  + ]:      26643 :     } else if (error != EAGAIN) {
     455         [ #  # ]:          0 :         VLOG_WARN("%s: accept failed (%s)",
     456                 :            :                   pstream_get_name(pconn->pstream), ovs_strerror(error));
     457                 :          0 :         pstream_close(pconn->pstream);
     458                 :          0 :         pconn->pstream = NULL;
     459                 :          0 :         dev->conn.type = NONE;
     460                 :            :     }
     461                 :            : 
     462         [ +  + ]:      52975 :     for (i = 0; i < pconn->n_streams; ) {
     463                 :      26272 :         struct dummy_packet_stream *s = pconn->streams[i];
     464                 :            : 
     465                 :      26272 :         error = dummy_packet_stream_run(dev, s);
     466         [ +  + ]:      26272 :         if (error) {
     467         [ -  + ]:         44 :             VLOG_DBG("%s: closing connection (%s)",
     468                 :            :                      stream_get_name(s->stream),
     469                 :            :                      ovs_retval_to_string(error));
     470                 :         44 :             dummy_packet_stream_close(s);
     471                 :         44 :             free(s);
     472                 :         44 :             pconn->streams[i] = pconn->streams[--pconn->n_streams];
     473                 :            :         } else {
     474                 :      26228 :             i++;
     475                 :            :         }
     476                 :            :     }
     477                 :      26703 : }
     478                 :            : 
     479                 :            : static void
     480                 :      34014 : dummy_rconn_run(struct netdev_dummy *dev)
     481                 :            : OVS_REQUIRES(dev->mutex)
     482                 :            : {
     483                 :      34014 :     struct dummy_packet_rconn *rconn = &dev->conn.u.rconn;
     484                 :            : 
     485         [ -  + ]:      34014 :     switch (reconnect_run(rconn->reconnect, time_msec())) {
     486                 :            :     case RECONNECT_CONNECT:
     487                 :            :         {
     488                 :            :             int error;
     489                 :            : 
     490         [ #  # ]:          0 :             if (rconn->rstream->stream) {
     491                 :          0 :                 error = stream_connect(rconn->rstream->stream);
     492                 :            :             } else {
     493                 :          0 :                 error = stream_open(reconnect_get_name(rconn->reconnect),
     494                 :          0 :                                     &rconn->rstream->stream, DSCP_DEFAULT);
     495                 :            :             }
     496                 :            : 
     497      [ #  #  # ]:          0 :             switch (error) {
     498                 :            :             case 0:
     499                 :          0 :                 reconnect_connected(rconn->reconnect, time_msec());
     500                 :          0 :                 break;
     501                 :            : 
     502                 :            :             case EAGAIN:
     503                 :          0 :                 reconnect_connecting(rconn->reconnect, time_msec());
     504                 :          0 :                 break;
     505                 :            : 
     506                 :            :             default:
     507                 :          0 :                 reconnect_connect_failed(rconn->reconnect, time_msec(), error);
     508                 :          0 :                 stream_close(rconn->rstream->stream);
     509                 :          0 :                 rconn->rstream->stream = NULL;
     510                 :          0 :                 break;
     511                 :            :             }
     512                 :            :         }
     513                 :          0 :         break;
     514                 :            : 
     515                 :            :     case RECONNECT_DISCONNECT:
     516                 :            :     case RECONNECT_PROBE:
     517                 :            :     default:
     518                 :      34014 :         break;
     519                 :            :     }
     520                 :            : 
     521         [ +  + ]:      34014 :     if (reconnect_is_connected(rconn->reconnect)) {
     522                 :            :         int err;
     523                 :            : 
     524                 :      34011 :         err = dummy_packet_stream_run(dev, rconn->rstream);
     525                 :            : 
     526         [ +  + ]:      34011 :         if (err) {
     527                 :          1 :             reconnect_disconnected(rconn->reconnect, time_msec(), err);
     528                 :          1 :             stream_close(rconn->rstream->stream);
     529                 :          1 :             rconn->rstream->stream = NULL;
     530                 :            :         }
     531                 :            :     }
     532                 :      34014 : }
     533                 :            : 
     534                 :            : static void
     535                 :     511610 : dummy_packet_conn_run(struct netdev_dummy *dev)
     536                 :            :     OVS_REQUIRES(dev->mutex)
     537                 :            : {
     538      [ +  +  + ]:     511610 :     switch (dev->conn.type) {
     539                 :            :     case PASSIVE:
     540                 :      26703 :         dummy_pconn_run(dev);
     541                 :      26703 :         break;
     542                 :            : 
     543                 :            :     case ACTIVE:
     544                 :      34014 :         dummy_rconn_run(dev);
     545                 :      34014 :         break;
     546                 :            : 
     547                 :            :     case NONE:
     548                 :            :     default:
     549                 :     450893 :         break;
     550                 :            :     }
     551                 :     511610 : }
     552                 :            : 
     553                 :            : static void
     554                 :     511610 : dummy_packet_conn_wait(struct dummy_packet_conn *conn)
     555                 :            : {
     556                 :            :     int i;
     557      [ +  +  + ]:     511610 :     switch (conn->type) {
     558                 :            :     case PASSIVE:
     559                 :      26703 :         pstream_wait(conn->u.pconn.pstream);
     560         [ +  + ]:      52931 :         for (i = 0; i < conn->u.pconn.n_streams; i++) {
     561                 :      26228 :             struct dummy_packet_stream *s = conn->u.pconn.streams[i];
     562                 :      26228 :             dummy_packet_stream_wait(s);
     563                 :            :         }
     564                 :      26703 :         break;
     565                 :            :     case ACTIVE:
     566         [ +  + ]:      34014 :         if (reconnect_is_connected(conn->u.rconn.reconnect)) {
     567                 :      34010 :             dummy_packet_stream_wait(conn->u.rconn.rstream);
     568                 :            :         }
     569                 :      34014 :         break;
     570                 :            : 
     571                 :            :     case NONE:
     572                 :            :     default:
     573                 :     450893 :         break;
     574                 :            :     }
     575                 :     511610 : }
     576                 :            : 
     577                 :            : static void
     578                 :      13397 : dummy_packet_conn_send(struct dummy_packet_conn *conn,
     579                 :            :                        const void *buffer, size_t size)
     580                 :            : {
     581                 :            :     int i;
     582                 :            : 
     583      [ +  +  + ]:      13397 :     switch (conn->type) {
     584                 :            :     case PASSIVE:
     585         [ +  + ]:       5209 :         for (i = 0; i < conn->u.pconn.n_streams; i++) {
     586                 :       2602 :             struct dummy_packet_stream *s = conn->u.pconn.streams[i];
     587                 :            : 
     588                 :       2602 :             dummy_packet_stream_send(s, buffer, size);
     589                 :       2602 :             pstream_wait(conn->u.pconn.pstream);
     590                 :            :         }
     591                 :       2607 :         break;
     592                 :            : 
     593                 :            :     case ACTIVE:
     594         [ +  - ]:       2120 :         if (reconnect_is_connected(conn->u.rconn.reconnect)) {
     595                 :       2120 :             dummy_packet_stream_send(conn->u.rconn.rstream, buffer, size);
     596                 :       2120 :             dummy_packet_stream_wait(conn->u.rconn.rstream);
     597                 :            :         }
     598                 :       2120 :         break;
     599                 :            : 
     600                 :            :     case NONE:
     601                 :            :     default:
     602                 :       8670 :         break;
     603                 :            :     }
     604                 :      13397 : }
     605                 :            : 
     606                 :            : static enum dummy_netdev_conn_state
     607                 :          5 : dummy_netdev_get_conn_state(struct dummy_packet_conn *conn)
     608                 :            : {
     609                 :            :     enum dummy_netdev_conn_state state;
     610                 :            : 
     611         [ +  - ]:          5 :     if (conn->type == ACTIVE) {
     612         [ +  - ]:          5 :         if (reconnect_is_connected(conn->u.rconn.reconnect)) {
     613                 :          5 :             state = CONN_STATE_CONNECTED;
     614                 :            :         } else {
     615                 :          5 :             state = CONN_STATE_NOT_CONNECTED;
     616                 :            :         }
     617                 :            :     } else {
     618                 :          0 :         state = CONN_STATE_UNKNOWN;
     619                 :            :     }
     620                 :            : 
     621                 :          5 :     return state;
     622                 :            : }
     623                 :            : 
     624                 :            : static void
     625                 :     321880 : netdev_dummy_run(const struct netdev_class *netdev_class)
     626                 :            : {
     627                 :            :     struct netdev_dummy *dev;
     628                 :            : 
     629                 :     321880 :     ovs_mutex_lock(&dummy_list_mutex);
     630         [ +  + ]:    2159424 :     LIST_FOR_EACH (dev, list_node, &dummy_list) {
     631         [ +  + ]:    1837544 :         if (netdev_get_class(&dev->up) != netdev_class) {
     632                 :    1325934 :             continue;
     633                 :            :         }
     634                 :     511610 :         ovs_mutex_lock(&dev->mutex);
     635                 :     511610 :         dummy_packet_conn_run(dev);
     636                 :     511610 :         ovs_mutex_unlock(&dev->mutex);
     637                 :            :     }
     638                 :     321880 :     ovs_mutex_unlock(&dummy_list_mutex);
     639                 :     321880 : }
     640                 :            : 
     641                 :            : static void
     642                 :     321880 : netdev_dummy_wait(const struct netdev_class *netdev_class)
     643                 :            : {
     644                 :            :     struct netdev_dummy *dev;
     645                 :            : 
     646                 :     321880 :     ovs_mutex_lock(&dummy_list_mutex);
     647         [ +  + ]:    2159424 :     LIST_FOR_EACH (dev, list_node, &dummy_list) {
     648         [ +  + ]:    1837544 :         if (netdev_get_class(&dev->up) != netdev_class) {
     649                 :    1325934 :             continue;
     650                 :            :         }
     651                 :     511610 :         ovs_mutex_lock(&dev->mutex);
     652                 :     511610 :         dummy_packet_conn_wait(&dev->conn);
     653                 :     511610 :         ovs_mutex_unlock(&dev->mutex);
     654                 :            :     }
     655                 :     321880 :     ovs_mutex_unlock(&dummy_list_mutex);
     656                 :     321880 : }
     657                 :            : 
     658                 :            : static struct netdev *
     659                 :       2963 : netdev_dummy_alloc(void)
     660                 :            : {
     661                 :       2963 :     struct netdev_dummy *netdev = xzalloc(sizeof *netdev);
     662                 :       2963 :     return &netdev->up;
     663                 :            : }
     664                 :            : 
     665                 :            : static int
     666                 :       2963 : netdev_dummy_construct(struct netdev *netdev_)
     667                 :            : {
     668                 :            :     static atomic_count next_n = ATOMIC_COUNT_INIT(0xaa550000);
     669                 :       2963 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     670                 :            :     unsigned int n;
     671                 :            : 
     672                 :       2963 :     n = atomic_count_inc(&next_n);
     673                 :            : 
     674                 :       2963 :     ovs_mutex_init(&netdev->mutex);
     675                 :       2963 :     ovs_mutex_lock(&netdev->mutex);
     676                 :       2963 :     netdev->hwaddr.ea[0] = 0xaa;
     677                 :       2963 :     netdev->hwaddr.ea[1] = 0x55;
     678                 :       2963 :     netdev->hwaddr.ea[2] = n >> 24;
     679                 :       2963 :     netdev->hwaddr.ea[3] = n >> 16;
     680                 :       2963 :     netdev->hwaddr.ea[4] = n >> 8;
     681                 :       2963 :     netdev->hwaddr.ea[5] = n;
     682                 :       2963 :     netdev->mtu = 1500;
     683                 :       2963 :     netdev->flags = 0;
     684                 :       2963 :     netdev->ifindex = -EOPNOTSUPP;
     685                 :       2963 :     netdev->requested_n_rxq = netdev_->n_rxq;
     686                 :       2963 :     netdev->requested_n_txq = netdev_->n_txq;
     687                 :       2963 :     netdev->numa_id = 0;
     688                 :            : 
     689                 :       2963 :     dummy_packet_conn_init(&netdev->conn);
     690                 :            : 
     691                 :       2963 :     ovs_list_init(&netdev->rxes);
     692                 :       2963 :     ovs_mutex_unlock(&netdev->mutex);
     693                 :            : 
     694                 :       2963 :     ovs_mutex_lock(&dummy_list_mutex);
     695                 :       2963 :     ovs_list_push_back(&dummy_list, &netdev->list_node);
     696                 :       2963 :     ovs_mutex_unlock(&dummy_list_mutex);
     697                 :            : 
     698                 :       2963 :     return 0;
     699                 :            : }
     700                 :            : 
     701                 :            : static void
     702                 :       1038 : netdev_dummy_destruct(struct netdev *netdev_)
     703                 :            : {
     704                 :       1038 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     705                 :            : 
     706                 :       1038 :     ovs_mutex_lock(&dummy_list_mutex);
     707                 :       1038 :     ovs_list_remove(&netdev->list_node);
     708                 :       1038 :     ovs_mutex_unlock(&dummy_list_mutex);
     709                 :            : 
     710                 :       1038 :     ovs_mutex_lock(&netdev->mutex);
     711                 :       1038 :     dummy_packet_conn_close(&netdev->conn);
     712                 :       1038 :     netdev->conn.type = NONE;
     713                 :            : 
     714                 :       1038 :     ovs_mutex_unlock(&netdev->mutex);
     715                 :       1038 :     ovs_mutex_destroy(&netdev->mutex);
     716                 :       1038 : }
     717                 :            : 
     718                 :            : static void
     719                 :       1038 : netdev_dummy_dealloc(struct netdev *netdev_)
     720                 :            : {
     721                 :       1038 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     722                 :            : 
     723                 :       1038 :     free(netdev);
     724                 :       1038 : }
     725                 :            : 
     726                 :            : static int
     727                 :         80 : netdev_dummy_get_config(const struct netdev *dev, struct smap *args)
     728                 :            : {
     729                 :         80 :     struct netdev_dummy *netdev = netdev_dummy_cast(dev);
     730                 :            : 
     731                 :         80 :     ovs_mutex_lock(&netdev->mutex);
     732                 :            : 
     733         [ +  + ]:         80 :     if (netdev->ifindex >= 0) {
     734                 :          2 :         smap_add_format(args, "ifindex", "%d", netdev->ifindex);
     735                 :            :     }
     736                 :            : 
     737                 :         80 :     dummy_packet_conn_get_config(&netdev->conn, args);
     738                 :            : 
     739                 :            :     /* 'dummy-pmd' specific config. */
     740         [ +  + ]:         80 :     if (!netdev_is_pmd(dev)) {
     741                 :         74 :         goto exit;
     742                 :            :     }
     743                 :          6 :     smap_add_format(args, "requested_rx_queues", "%d", netdev->requested_n_rxq);
     744                 :          6 :     smap_add_format(args, "configured_rx_queues", "%d", dev->n_rxq);
     745                 :          6 :     smap_add_format(args, "requested_tx_queues", "%d", netdev->requested_n_txq);
     746                 :          6 :     smap_add_format(args, "configured_tx_queues", "%d", dev->n_txq);
     747                 :            : 
     748                 :            : exit:
     749                 :         80 :     ovs_mutex_unlock(&netdev->mutex);
     750                 :         80 :     return 0;
     751                 :            : }
     752                 :            : 
     753                 :            : static int
     754                 :       1138 : netdev_dummy_get_addr_list(const struct netdev *netdev_, struct in6_addr **paddr,
     755                 :            :                            struct in6_addr **pmask, int *n_addr)
     756                 :            : {
     757                 :       1138 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     758                 :       1138 :     int cnt = 0, i = 0, err = 0;
     759                 :            :     struct in6_addr *addr, *mask;
     760                 :            : 
     761                 :       1138 :     ovs_mutex_lock(&netdev->mutex);
     762         [ +  + ]:       1138 :     if (netdev->address.s_addr != INADDR_ANY) {
     763                 :        400 :         cnt++;
     764                 :            :     }
     765                 :            : 
     766         [ +  + ]:       1138 :     if (ipv6_addr_is_set(&netdev->ipv6)) {
     767                 :          6 :         cnt++;
     768                 :            :     }
     769         [ +  + ]:       1138 :     if (!cnt) {
     770                 :        738 :         err = EADDRNOTAVAIL;
     771                 :        738 :         goto out;
     772                 :            :     }
     773                 :        400 :     addr = xmalloc(sizeof *addr * cnt);
     774                 :        400 :     mask = xmalloc(sizeof *mask * cnt);
     775         [ +  - ]:        400 :     if (netdev->address.s_addr != INADDR_ANY) {
     776                 :        400 :         in6_addr_set_mapped_ipv4(&addr[i], netdev->address.s_addr);
     777                 :        400 :         in6_addr_set_mapped_ipv4(&mask[i], netdev->netmask.s_addr);
     778                 :        400 :         i++;
     779                 :            :     }
     780                 :            : 
     781         [ +  + ]:        400 :     if (ipv6_addr_is_set(&netdev->ipv6)) {
     782                 :          6 :         memcpy(&addr[i], &netdev->ipv6, sizeof *addr);
     783                 :          6 :         memcpy(&mask[i], &netdev->ipv6_mask, sizeof *mask);
     784                 :          6 :         i++;
     785                 :            :     }
     786         [ +  - ]:        400 :     if (paddr) {
     787                 :        400 :         *paddr = addr;
     788                 :        400 :         *pmask = mask;
     789                 :        400 :         *n_addr = cnt;
     790                 :            :     } else {
     791                 :          0 :         free(addr);
     792                 :          0 :         free(mask);
     793                 :            :     }
     794                 :            : out:
     795                 :       1138 :     ovs_mutex_unlock(&netdev->mutex);
     796                 :            : 
     797                 :       1138 :     return err;
     798                 :            : }
     799                 :            : 
     800                 :            : static int
     801                 :         45 : netdev_dummy_set_in4(struct netdev *netdev_, struct in_addr address,
     802                 :            :                      struct in_addr netmask)
     803                 :            : {
     804                 :         45 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     805                 :            : 
     806                 :         45 :     ovs_mutex_lock(&netdev->mutex);
     807                 :         45 :     netdev->address = address;
     808                 :         45 :     netdev->netmask = netmask;
     809                 :         45 :     netdev_change_seq_changed(netdev_);
     810                 :         45 :     ovs_mutex_unlock(&netdev->mutex);
     811                 :            : 
     812                 :         45 :     return 0;
     813                 :            : }
     814                 :            : 
     815                 :            : static int
     816                 :          2 : netdev_dummy_set_in6(struct netdev *netdev_, struct in6_addr *in6,
     817                 :            :                      struct in6_addr *mask)
     818                 :            : {
     819                 :          2 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     820                 :            : 
     821                 :          2 :     ovs_mutex_lock(&netdev->mutex);
     822                 :          2 :     netdev->ipv6 = *in6;
     823                 :          2 :     netdev->ipv6_mask = *mask;
     824                 :          2 :     netdev_change_seq_changed(netdev_);
     825                 :          2 :     ovs_mutex_unlock(&netdev->mutex);
     826                 :            : 
     827                 :          2 :     return 0;
     828                 :            : }
     829                 :            : 
     830                 :            : static int
     831                 :       5296 : netdev_dummy_set_config(struct netdev *netdev_, const struct smap *args)
     832                 :            : {
     833                 :       5296 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     834                 :            :     const char *pcap;
     835                 :            :     int new_n_rxq, new_n_txq, new_numa_id;
     836                 :            : 
     837                 :       5296 :     ovs_mutex_lock(&netdev->mutex);
     838                 :       5296 :     netdev->ifindex = smap_get_int(args, "ifindex", -EOPNOTSUPP);
     839                 :            : 
     840                 :       5296 :     dummy_packet_conn_set_config(&netdev->conn, args);
     841                 :            : 
     842         [ +  + ]:       5296 :     if (netdev->rxq_pcap) {
     843                 :       1182 :         fclose(netdev->rxq_pcap);
     844                 :            :     }
     845 [ +  + ][ +  + ]:       5296 :     if (netdev->tx_pcap && netdev->tx_pcap != netdev->rxq_pcap) {
     846                 :       1179 :         fclose(netdev->tx_pcap);
     847                 :            :     }
     848                 :       5296 :     netdev->rxq_pcap = netdev->tx_pcap = NULL;
     849                 :       5296 :     pcap = smap_get(args, "pcap");
     850         [ +  + ]:       5296 :     if (pcap) {
     851                 :          8 :         netdev->rxq_pcap = netdev->tx_pcap = ovs_pcap_open(pcap, "ab");
     852                 :            :     } else {
     853                 :       5288 :         const char *rxq_pcap = smap_get(args, "rxq_pcap");
     854                 :       5288 :         const char *tx_pcap = smap_get(args, "tx_pcap");
     855                 :            : 
     856         [ +  + ]:       5288 :         if (rxq_pcap) {
     857                 :       1457 :             netdev->rxq_pcap = ovs_pcap_open(rxq_pcap, "ab");
     858                 :            :         }
     859         [ +  + ]:       5288 :         if (tx_pcap) {
     860                 :       1460 :             netdev->tx_pcap = ovs_pcap_open(tx_pcap, "ab");
     861                 :            :         }
     862                 :            :     }
     863                 :            : 
     864                 :       5296 :     netdev_change_seq_changed(netdev_);
     865                 :            : 
     866                 :            :     /* 'dummy-pmd' specific config. */
     867         [ +  + ]:       5296 :     if (!netdev_->netdev_class->is_pmd) {
     868                 :       5251 :         goto exit;
     869                 :            :     }
     870                 :            : 
     871         [ +  + ]:         45 :     new_n_rxq = MAX(smap_get_int(args, "n_rxq", netdev->requested_n_rxq), 1);
     872         [ -  + ]:         45 :     new_n_txq = MAX(smap_get_int(args, "n_txq", netdev->requested_n_txq), 1);
     873                 :         45 :     new_numa_id = smap_get_int(args, "numa_id", 0);
     874         [ +  + ]:         45 :     if (new_n_rxq != netdev->requested_n_rxq
     875         [ +  - ]:         36 :         || new_n_txq != netdev->requested_n_txq
     876         [ +  + ]:         36 :         || new_numa_id != netdev->requested_numa_id) {
     877                 :         10 :         netdev->requested_n_rxq = new_n_rxq;
     878                 :         10 :         netdev->requested_n_txq = new_n_txq;
     879                 :         10 :         netdev->requested_numa_id = new_numa_id;
     880                 :         10 :         netdev_request_reconfigure(netdev_);
     881                 :            :     }
     882                 :            : 
     883                 :            : exit:
     884                 :       5296 :     ovs_mutex_unlock(&netdev->mutex);
     885                 :       5296 :     return 0;
     886                 :            : }
     887                 :            : 
     888                 :            : static int
     889                 :       2368 : netdev_dummy_get_numa_id(const struct netdev *netdev_)
     890                 :            : {
     891                 :       2368 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     892                 :            : 
     893                 :       2368 :     ovs_mutex_lock(&netdev->mutex);
     894                 :       2368 :     int numa_id = netdev->numa_id;
     895                 :       2368 :     ovs_mutex_unlock(&netdev->mutex);
     896                 :            : 
     897                 :       2368 :     return numa_id;
     898                 :            : }
     899                 :            : 
     900                 :            : /* Sets the number of tx queues and rx queues for the dummy PMD interface. */
     901                 :            : static int
     902                 :         10 : netdev_dummy_reconfigure(struct netdev *netdev_)
     903                 :            : {
     904                 :         10 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
     905                 :            : 
     906                 :         10 :     ovs_mutex_lock(&netdev->mutex);
     907                 :            : 
     908                 :         10 :     netdev_->n_txq = netdev->requested_n_txq;
     909                 :         10 :     netdev_->n_rxq = netdev->requested_n_rxq;
     910                 :         10 :     netdev->numa_id = netdev->requested_numa_id;
     911                 :            : 
     912                 :         10 :     ovs_mutex_unlock(&netdev->mutex);
     913                 :         10 :     return 0;
     914                 :            : }
     915                 :            : 
     916                 :            : static struct netdev_rxq *
     917                 :       2258 : netdev_dummy_rxq_alloc(void)
     918                 :            : {
     919                 :       2258 :     struct netdev_rxq_dummy *rx = xzalloc(sizeof *rx);
     920                 :       2258 :     return &rx->up;
     921                 :            : }
     922                 :            : 
     923                 :            : static int
     924                 :       2258 : netdev_dummy_rxq_construct(struct netdev_rxq *rxq_)
     925                 :            : {
     926                 :       2258 :     struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
     927                 :       2258 :     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
     928                 :            : 
     929                 :       2258 :     ovs_mutex_lock(&netdev->mutex);
     930                 :       2258 :     ovs_list_push_back(&netdev->rxes, &rx->node);
     931                 :       2258 :     ovs_list_init(&rx->recv_queue);
     932                 :       2258 :     rx->recv_queue_len = 0;
     933                 :       2258 :     rx->seq = seq_create();
     934                 :       2258 :     ovs_mutex_unlock(&netdev->mutex);
     935                 :            : 
     936                 :       2258 :     return 0;
     937                 :            : }
     938                 :            : 
     939                 :            : static void
     940                 :        307 : netdev_dummy_rxq_destruct(struct netdev_rxq *rxq_)
     941                 :            : {
     942                 :        307 :     struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
     943                 :        307 :     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
     944                 :            : 
     945                 :        307 :     ovs_mutex_lock(&netdev->mutex);
     946                 :        307 :     ovs_list_remove(&rx->node);
     947                 :        307 :     pkt_list_delete(&rx->recv_queue);
     948                 :        307 :     ovs_mutex_unlock(&netdev->mutex);
     949                 :        307 :     seq_destroy(rx->seq);
     950                 :        307 : }
     951                 :            : 
     952                 :            : static void
     953                 :        307 : netdev_dummy_rxq_dealloc(struct netdev_rxq *rxq_)
     954                 :            : {
     955                 :        307 :     struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
     956                 :            : 
     957                 :        307 :     free(rx);
     958                 :        307 : }
     959                 :            : 
     960                 :            : static int
     961                 :   26314786 : netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet_batch *batch)
     962                 :            : {
     963                 :   26314786 :     struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
     964                 :   26314638 :     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
     965                 :            :     struct dp_packet *packet;
     966                 :            : 
     967                 :   26313556 :     ovs_mutex_lock(&netdev->mutex);
     968         [ +  + ]:   26322084 :     if (!ovs_list_is_empty(&rx->recv_queue)) {
     969                 :            :         struct pkt_list_node *pkt_node;
     970                 :            : 
     971                 :       8619 :         ASSIGN_CONTAINER(pkt_node, ovs_list_pop_front(&rx->recv_queue), list_node);
     972                 :       8619 :         packet = pkt_node->pkt;
     973                 :       8619 :         free(pkt_node);
     974                 :       8619 :         rx->recv_queue_len--;
     975                 :            :     } else {
     976                 :   26313241 :         packet = NULL;
     977                 :            :     }
     978                 :   26321860 :     ovs_mutex_unlock(&netdev->mutex);
     979                 :            : 
     980         [ +  + ]:   26322579 :     if (!packet) {
     981         [ +  + ]:   26313960 :         if (netdev_is_pmd(&netdev->up)) {
     982                 :            :             /* If 'netdev' is a PMD device, this is called as part of the PMD
     983                 :            :              * thread busy loop.  We yield here (without quiescing) for two
     984                 :            :              * reasons:
     985                 :            :              *
     986                 :            :              * - To reduce the CPU utilization during the testsuite
     987                 :            :              * - To give valgrind a chance to switch thread. According
     988                 :            :              *   to the valgrind documentation, there's a big lock that
     989                 :            :              *   prevents multiple thread from being executed at the same
     990                 :            :              *   time.  On my system, without this sleep, the pmd threads
     991                 :            :              *   testcases fail under valgrind, because ovs-vswitchd becomes
     992                 :            :              *   unresponsive. */
     993                 :   25806141 :             sched_yield();
     994                 :            :         }
     995                 :   26320169 :         return EAGAIN;
     996                 :            :     }
     997                 :       8619 :     ovs_mutex_lock(&netdev->mutex);
     998                 :       8619 :     netdev->stats.rx_packets++;
     999                 :       8619 :     netdev->stats.rx_bytes += dp_packet_size(packet);
    1000                 :       8619 :     ovs_mutex_unlock(&netdev->mutex);
    1001                 :            : 
    1002                 :       8619 :     batch->packets[0] = packet;
    1003                 :       8619 :     batch->count = 1;
    1004                 :       8619 :     return 0;
    1005                 :            : }
    1006                 :            : 
    1007                 :            : static void
    1008                 :     510552 : netdev_dummy_rxq_wait(struct netdev_rxq *rxq_)
    1009                 :            : {
    1010                 :     510552 :     struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
    1011                 :     510552 :     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
    1012                 :     510552 :     uint64_t seq = seq_read(rx->seq);
    1013                 :            : 
    1014                 :     510552 :     ovs_mutex_lock(&netdev->mutex);
    1015         [ +  + ]:     510552 :     if (!ovs_list_is_empty(&rx->recv_queue)) {
    1016                 :       8565 :         poll_immediate_wake();
    1017                 :            :     } else {
    1018                 :     501987 :         seq_wait(rx->seq, seq);
    1019                 :            :     }
    1020                 :     510552 :     ovs_mutex_unlock(&netdev->mutex);
    1021                 :     510552 : }
    1022                 :            : 
    1023                 :            : static int
    1024                 :          0 : netdev_dummy_rxq_drain(struct netdev_rxq *rxq_)
    1025                 :            : {
    1026                 :          0 :     struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
    1027                 :          0 :     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
    1028                 :            : 
    1029                 :          0 :     ovs_mutex_lock(&netdev->mutex);
    1030                 :          0 :     pkt_list_delete(&rx->recv_queue);
    1031                 :          0 :     rx->recv_queue_len = 0;
    1032                 :          0 :     ovs_mutex_unlock(&netdev->mutex);
    1033                 :            : 
    1034                 :          0 :     seq_change(rx->seq);
    1035                 :            : 
    1036                 :          0 :     return 0;
    1037                 :            : }
    1038                 :            : 
    1039                 :            : static int
    1040                 :      13397 : netdev_dummy_send(struct netdev *netdev, int qid OVS_UNUSED,
    1041                 :            :                   struct dp_packet_batch *batch, bool may_steal,
    1042                 :            :                   bool concurrent_txq OVS_UNUSED)
    1043                 :            : {
    1044                 :      13397 :     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
    1045                 :      13397 :     int error = 0;
    1046                 :            :     int i;
    1047                 :            : 
    1048         [ +  + ]:      26794 :     for (i = 0; i < batch->count; i++) {
    1049                 :      13397 :         const void *buffer = dp_packet_data(batch->packets[i]);
    1050                 :      13397 :         size_t size = dp_packet_size(batch->packets[i]);
    1051                 :            : 
    1052                 :      13397 :         size -= dp_packet_get_cutlen(batch->packets[i]);
    1053                 :            : 
    1054         [ -  + ]:      13397 :         if (size < ETH_HEADER_LEN) {
    1055                 :          0 :             error = EMSGSIZE;
    1056                 :          0 :             break;
    1057                 :            :         } else {
    1058                 :      13397 :             const struct eth_header *eth = buffer;
    1059                 :            :             int max_size;
    1060                 :            : 
    1061                 :      13397 :             ovs_mutex_lock(&dev->mutex);
    1062                 :      13397 :             max_size = dev->mtu + ETH_HEADER_LEN;
    1063                 :      13397 :             ovs_mutex_unlock(&dev->mutex);
    1064                 :            : 
    1065         [ +  + ]:      13397 :             if (eth->eth_type == htons(ETH_TYPE_VLAN)) {
    1066                 :         38 :                 max_size += VLAN_HEADER_LEN;
    1067                 :            :             }
    1068         [ -  + ]:      13397 :             if (size > max_size) {
    1069                 :          0 :                 error = EMSGSIZE;
    1070                 :          0 :                 break;
    1071                 :            :             }
    1072                 :            :         }
    1073                 :            : 
    1074                 :      13397 :         ovs_mutex_lock(&dev->mutex);
    1075                 :      13397 :         dev->stats.tx_packets++;
    1076                 :      13397 :         dev->stats.tx_bytes += size;
    1077                 :            : 
    1078                 :      13397 :         dummy_packet_conn_send(&dev->conn, buffer, size);
    1079                 :            : 
    1080                 :            :         /* Reply to ARP requests for 'dev''s assigned IP address. */
    1081         [ +  + ]:      13397 :         if (dev->address.s_addr) {
    1082                 :            :             struct dp_packet packet;
    1083                 :            :             struct flow flow;
    1084                 :            : 
    1085                 :        336 :             dp_packet_use_const(&packet, buffer, size);
    1086                 :        336 :             flow_extract(&packet, &flow);
    1087         [ +  + ]:        336 :             if (flow.dl_type == htons(ETH_TYPE_ARP)
    1088         [ -  + ]:          1 :                 && flow.nw_proto == ARP_OP_REQUEST
    1089         [ #  # ]:          0 :                 && flow.nw_dst == dev->address.s_addr) {
    1090                 :          0 :                 struct dp_packet *reply = dp_packet_new(0);
    1091                 :          0 :                 compose_arp(reply, ARP_OP_REPLY, dev->hwaddr, flow.dl_src,
    1092                 :            :                             false, flow.nw_dst, flow.nw_src);
    1093                 :        336 :                 netdev_dummy_queue_packet(dev, reply, 0);
    1094                 :            :             }
    1095                 :            :         }
    1096                 :            : 
    1097         [ +  + ]:      13397 :         if (dev->tx_pcap) {
    1098                 :            :             struct dp_packet packet;
    1099                 :            : 
    1100                 :      10282 :             dp_packet_use_const(&packet, buffer, size);
    1101                 :      10282 :             ovs_pcap_write(dev->tx_pcap, &packet);
    1102                 :      10282 :             fflush(dev->tx_pcap);
    1103                 :            :         }
    1104                 :            : 
    1105                 :      13397 :         ovs_mutex_unlock(&dev->mutex);
    1106                 :            :     }
    1107                 :            : 
    1108                 :      13397 :     dp_packet_delete_batch(batch, may_steal);
    1109                 :            : 
    1110                 :      13397 :     return error;
    1111                 :            : }
    1112                 :            : 
    1113                 :            : static int
    1114                 :       2629 : netdev_dummy_set_etheraddr(struct netdev *netdev, const struct eth_addr mac)
    1115                 :            : {
    1116                 :       2629 :     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
    1117                 :            : 
    1118                 :       2629 :     ovs_mutex_lock(&dev->mutex);
    1119         [ +  + ]:       2629 :     if (!eth_addr_equals(dev->hwaddr, mac)) {
    1120                 :        641 :         dev->hwaddr = mac;
    1121                 :        641 :         netdev_change_seq_changed(netdev);
    1122                 :            :     }
    1123                 :       2629 :     ovs_mutex_unlock(&dev->mutex);
    1124                 :            : 
    1125                 :       2629 :     return 0;
    1126                 :            : }
    1127                 :            : 
    1128                 :            : static int
    1129                 :      17009 : netdev_dummy_get_etheraddr(const struct netdev *netdev, struct eth_addr *mac)
    1130                 :            : {
    1131                 :      17009 :     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
    1132                 :            : 
    1133                 :      17009 :     ovs_mutex_lock(&dev->mutex);
    1134                 :      17009 :     *mac = dev->hwaddr;
    1135                 :      17009 :     ovs_mutex_unlock(&dev->mutex);
    1136                 :            : 
    1137                 :      17009 :     return 0;
    1138                 :            : }
    1139                 :            : 
    1140                 :            : static int
    1141                 :      20278 : netdev_dummy_get_mtu(const struct netdev *netdev, int *mtup)
    1142                 :            : {
    1143                 :      20278 :     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
    1144                 :            : 
    1145                 :      20278 :     ovs_mutex_lock(&dev->mutex);
    1146                 :      20278 :     *mtup = dev->mtu;
    1147                 :      20278 :     ovs_mutex_unlock(&dev->mutex);
    1148                 :            : 
    1149                 :      20278 :     return 0;
    1150                 :            : }
    1151                 :            : 
    1152                 :            : static int
    1153                 :        330 : netdev_dummy_set_mtu(struct netdev *netdev, int mtu)
    1154                 :            : {
    1155                 :        330 :     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
    1156                 :            : 
    1157                 :        330 :     ovs_mutex_lock(&dev->mutex);
    1158         [ +  + ]:        330 :     if (dev->mtu != mtu) {
    1159                 :          8 :         dev->mtu = mtu;
    1160                 :          8 :         netdev_change_seq_changed(netdev);
    1161                 :            :     }
    1162                 :        330 :     ovs_mutex_unlock(&dev->mutex);
    1163                 :            : 
    1164                 :        330 :     return 0;
    1165                 :            : }
    1166                 :            : 
    1167                 :            : static int
    1168                 :       4220 : netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
    1169                 :            : {
    1170                 :       4220 :     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
    1171                 :            : 
    1172                 :       4220 :     ovs_mutex_lock(&dev->mutex);
    1173                 :            :     /* Passing only collected counters */
    1174                 :       4220 :     stats->tx_packets = dev->stats.tx_packets;
    1175                 :       4220 :     stats->tx_bytes = dev->stats.tx_bytes;
    1176                 :       4220 :     stats->rx_packets = dev->stats.rx_packets;
    1177                 :       4220 :     stats->rx_bytes = dev->stats.rx_bytes;
    1178                 :       4220 :     ovs_mutex_unlock(&dev->mutex);
    1179                 :            : 
    1180                 :       4220 :     return 0;
    1181                 :            : }
    1182                 :            : 
    1183                 :            : static int
    1184                 :          1 : netdev_dummy_get_queue(const struct netdev *netdev OVS_UNUSED,
    1185                 :            :                        unsigned int queue_id, struct smap *details OVS_UNUSED)
    1186                 :            : {
    1187         [ -  + ]:          1 :     if (queue_id == 0) {
    1188                 :          0 :         return 0;
    1189                 :            :     } else {
    1190                 :          1 :         return EINVAL;
    1191                 :            :     }
    1192                 :            : }
    1193                 :            : 
    1194                 :            : static void
    1195                 :         20 : netdev_dummy_init_queue_stats(struct netdev_queue_stats *stats)
    1196                 :            : {
    1197                 :         20 :     *stats = (struct netdev_queue_stats) {
    1198                 :            :         .tx_bytes = UINT64_MAX,
    1199                 :            :         .tx_packets = UINT64_MAX,
    1200                 :            :         .tx_errors = UINT64_MAX,
    1201                 :            :         .created = LLONG_MIN,
    1202                 :            :     };
    1203                 :         20 : }
    1204                 :            : 
    1205                 :            : static int
    1206                 :         20 : netdev_dummy_get_queue_stats(const struct netdev *netdev OVS_UNUSED,
    1207                 :            :                              unsigned int queue_id,
    1208                 :            :                              struct netdev_queue_stats *stats)
    1209                 :            : {
    1210         [ +  + ]:         20 :     if (queue_id == 0) {
    1211                 :         10 :         netdev_dummy_init_queue_stats(stats);
    1212                 :         10 :         return 0;
    1213                 :            :     } else {
    1214                 :         10 :         return EINVAL;
    1215                 :            :     }
    1216                 :            : }
    1217                 :            : 
    1218                 :            : struct netdev_dummy_queue_state {
    1219                 :            :     unsigned int next_queue;
    1220                 :            : };
    1221                 :            : 
    1222                 :            : static int
    1223                 :         13 : netdev_dummy_queue_dump_start(const struct netdev *netdev OVS_UNUSED,
    1224                 :            :                               void **statep)
    1225                 :            : {
    1226                 :         13 :     struct netdev_dummy_queue_state *state = xmalloc(sizeof *state);
    1227                 :         13 :     state->next_queue = 0;
    1228                 :         13 :     *statep = state;
    1229                 :         13 :     return 0;
    1230                 :            : }
    1231                 :            : 
    1232                 :            : static int
    1233                 :         26 : netdev_dummy_queue_dump_next(const struct netdev *netdev OVS_UNUSED,
    1234                 :            :                              void *state_,
    1235                 :            :                              unsigned int *queue_id,
    1236                 :            :                              struct smap *details OVS_UNUSED)
    1237                 :            : {
    1238                 :         26 :     struct netdev_dummy_queue_state *state = state_;
    1239         [ +  + ]:         26 :     if (state->next_queue == 0) {
    1240                 :         13 :         *queue_id = 0;
    1241                 :         13 :         state->next_queue++;
    1242                 :         13 :         return 0;
    1243                 :            :     } else {
    1244                 :         13 :         return EOF;
    1245                 :            :     }
    1246                 :            : }
    1247                 :            : 
    1248                 :            : static int
    1249                 :         13 : netdev_dummy_queue_dump_done(const struct netdev *netdev OVS_UNUSED,
    1250                 :            :                              void *state)
    1251                 :            : {
    1252                 :         13 :     free(state);
    1253                 :         13 :     return 0;
    1254                 :            : }
    1255                 :            : 
    1256                 :            : static int
    1257                 :         10 : netdev_dummy_dump_queue_stats(const struct netdev *netdev OVS_UNUSED,
    1258                 :            :                               void (*cb)(unsigned int queue_id,
    1259                 :            :                                          struct netdev_queue_stats *,
    1260                 :            :                                          void *aux),
    1261                 :            :                               void *aux)
    1262                 :            : {
    1263                 :            :     struct netdev_queue_stats stats;
    1264                 :         10 :     netdev_dummy_init_queue_stats(&stats);
    1265                 :         10 :     cb(0, &stats, aux);
    1266                 :         10 :     return 0;
    1267                 :            : }
    1268                 :            : 
    1269                 :            : static int
    1270                 :       6966 : netdev_dummy_get_ifindex(const struct netdev *netdev)
    1271                 :            : {
    1272                 :       6966 :     struct netdev_dummy *dev = netdev_dummy_cast(netdev);
    1273                 :            :     int ifindex;
    1274                 :            : 
    1275                 :       6966 :     ovs_mutex_lock(&dev->mutex);
    1276                 :       6966 :     ifindex = dev->ifindex;
    1277                 :       6966 :     ovs_mutex_unlock(&dev->mutex);
    1278                 :            : 
    1279                 :       6966 :     return ifindex;
    1280                 :            : }
    1281                 :            : 
    1282                 :            : static int
    1283                 :      49844 : netdev_dummy_update_flags__(struct netdev_dummy *netdev,
    1284                 :            :                             enum netdev_flags off, enum netdev_flags on,
    1285                 :            :                             enum netdev_flags *old_flagsp)
    1286                 :            :     OVS_REQUIRES(netdev->mutex)
    1287                 :            : {
    1288         [ -  + ]:      49844 :     if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
    1289                 :          0 :         return EINVAL;
    1290                 :            :     }
    1291                 :            : 
    1292                 :      49844 :     *old_flagsp = netdev->flags;
    1293                 :      49844 :     netdev->flags |= on;
    1294                 :      49844 :     netdev->flags &= ~off;
    1295         [ +  + ]:      49844 :     if (*old_flagsp != netdev->flags) {
    1296                 :       3129 :         netdev_change_seq_changed(&netdev->up);
    1297                 :            :     }
    1298                 :            : 
    1299                 :      49844 :     return 0;
    1300                 :            : }
    1301                 :            : 
    1302                 :            : static int
    1303                 :      49778 : netdev_dummy_update_flags(struct netdev *netdev_,
    1304                 :            :                           enum netdev_flags off, enum netdev_flags on,
    1305                 :            :                           enum netdev_flags *old_flagsp)
    1306                 :            : {
    1307                 :      49778 :     struct netdev_dummy *netdev = netdev_dummy_cast(netdev_);
    1308                 :            :     int error;
    1309                 :            : 
    1310                 :      49778 :     ovs_mutex_lock(&netdev->mutex);
    1311                 :      49778 :     error = netdev_dummy_update_flags__(netdev, off, on, old_flagsp);
    1312                 :      49778 :     ovs_mutex_unlock(&netdev->mutex);
    1313                 :            : 
    1314                 :      49778 :     return error;
    1315                 :            : }
    1316                 :            : 
    1317                 :            : /* Helper functions. */
    1318                 :            : 
    1319                 :            : #define NETDEV_DUMMY_CLASS(NAME, PMD, RECOFIGURE)               \
    1320                 :            : {                                                               \
    1321                 :            :     NAME,                                                       \
    1322                 :            :     PMD,                        /* is_pmd */                    \
    1323                 :            :     NULL,                       /* init */                      \
    1324                 :            :     netdev_dummy_run,                                           \
    1325                 :            :     netdev_dummy_wait,                                          \
    1326                 :            :                                                                 \
    1327                 :            :     netdev_dummy_alloc,                                         \
    1328                 :            :     netdev_dummy_construct,                                     \
    1329                 :            :     netdev_dummy_destruct,                                      \
    1330                 :            :     netdev_dummy_dealloc,                                       \
    1331                 :            :     netdev_dummy_get_config,                                    \
    1332                 :            :     netdev_dummy_set_config,                                    \
    1333                 :            :     NULL,                       /* get_tunnel_config */         \
    1334                 :            :     NULL,                       /* build header */              \
    1335                 :            :     NULL,                       /* push header */               \
    1336                 :            :     NULL,                       /* pop header */                \
    1337                 :            :     netdev_dummy_get_numa_id,                                   \
    1338                 :            :     NULL,                       /* set_tx_multiq */             \
    1339                 :            :                                                                 \
    1340                 :            :     netdev_dummy_send,          /* send */                      \
    1341                 :            :     NULL,                       /* send_wait */                 \
    1342                 :            :                                                                 \
    1343                 :            :     netdev_dummy_set_etheraddr,                                 \
    1344                 :            :     netdev_dummy_get_etheraddr,                                 \
    1345                 :            :     netdev_dummy_get_mtu,                                       \
    1346                 :            :     netdev_dummy_set_mtu,                                       \
    1347                 :            :     netdev_dummy_get_ifindex,                                   \
    1348                 :            :     NULL,                       /* get_carrier */               \
    1349                 :            :     NULL,                       /* get_carrier_resets */        \
    1350                 :            :     NULL,                       /* get_miimon */                \
    1351                 :            :     netdev_dummy_get_stats,                                     \
    1352                 :            :                                                                 \
    1353                 :            :     NULL,                       /* get_features */              \
    1354                 :            :     NULL,                       /* set_advertisements */        \
    1355                 :            :                                                                 \
    1356                 :            :     NULL,                       /* set_policing */              \
    1357                 :            :     NULL,                       /* get_qos_types */             \
    1358                 :            :     NULL,                       /* get_qos_capabilities */      \
    1359                 :            :     NULL,                       /* get_qos */                   \
    1360                 :            :     NULL,                       /* set_qos */                   \
    1361                 :            :     netdev_dummy_get_queue,                                     \
    1362                 :            :     NULL,                       /* set_queue */                 \
    1363                 :            :     NULL,                       /* delete_queue */              \
    1364                 :            :     netdev_dummy_get_queue_stats,                               \
    1365                 :            :     netdev_dummy_queue_dump_start,                              \
    1366                 :            :     netdev_dummy_queue_dump_next,                               \
    1367                 :            :     netdev_dummy_queue_dump_done,                               \
    1368                 :            :     netdev_dummy_dump_queue_stats,                              \
    1369                 :            :                                                                 \
    1370                 :            :     NULL,                       /* set_in4 */                   \
    1371                 :            :     netdev_dummy_get_addr_list,                                 \
    1372                 :            :     NULL,                       /* add_router */                \
    1373                 :            :     NULL,                       /* get_next_hop */              \
    1374                 :            :     NULL,                       /* get_status */                \
    1375                 :            :     NULL,                       /* arp_lookup */                \
    1376                 :            :                                                                 \
    1377                 :            :     netdev_dummy_update_flags,                                  \
    1378                 :            :     RECOFIGURE,                                                 \
    1379                 :            :                                                                 \
    1380                 :            :     netdev_dummy_rxq_alloc,                                     \
    1381                 :            :     netdev_dummy_rxq_construct,                                 \
    1382                 :            :     netdev_dummy_rxq_destruct,                                  \
    1383                 :            :     netdev_dummy_rxq_dealloc,                                   \
    1384                 :            :     netdev_dummy_rxq_recv,                                      \
    1385                 :            :     netdev_dummy_rxq_wait,                                      \
    1386                 :            :     netdev_dummy_rxq_drain,                                     \
    1387                 :            : }
    1388                 :            : 
    1389                 :            : static const struct netdev_class dummy_class =
    1390                 :            :     NETDEV_DUMMY_CLASS("dummy", false, NULL);
    1391                 :            : 
    1392                 :            : static const struct netdev_class dummy_internal_class =
    1393                 :            :     NETDEV_DUMMY_CLASS("dummy-internal", false, NULL);
    1394                 :            : 
    1395                 :            : static const struct netdev_class dummy_pmd_class =
    1396                 :            :     NETDEV_DUMMY_CLASS("dummy-pmd", true,
    1397                 :            :                        netdev_dummy_reconfigure);
    1398                 :            : 
    1399                 :            : static void
    1400                 :        352 : pkt_list_delete(struct ovs_list *l)
    1401                 :            : {
    1402                 :            :     struct pkt_list_node *pkt;
    1403                 :            : 
    1404         [ -  + ]:        352 :     LIST_FOR_EACH_POP(pkt, list_node, l) {
    1405                 :          0 :         dp_packet_delete(pkt->pkt);
    1406                 :          0 :         free(pkt);
    1407                 :            :     }
    1408                 :        352 : }
    1409                 :            : 
    1410                 :            : static struct dp_packet *
    1411                 :       3903 : eth_from_packet_or_flow(const char *s)
    1412                 :            : {
    1413                 :            :     enum odp_key_fitness fitness;
    1414                 :            :     struct dp_packet *packet;
    1415                 :            :     struct ofpbuf odp_key;
    1416                 :            :     struct flow flow;
    1417                 :            :     int error;
    1418                 :            : 
    1419         [ +  + ]:       3903 :     if (!eth_from_hex(s, &packet)) {
    1420                 :       2723 :         return packet;
    1421                 :            :     }
    1422                 :            : 
    1423                 :            :     /* Convert string to datapath key.
    1424                 :            :      *
    1425                 :            :      * It would actually be nicer to parse an OpenFlow-like flow key here, but
    1426                 :            :      * the code for that currently calls exit() on parse error.  We have to
    1427                 :            :      * settle for parsing a datapath key for now.
    1428                 :            :      */
    1429                 :       1180 :     ofpbuf_init(&odp_key, 0);
    1430                 :       1180 :     error = odp_flow_from_string(s, NULL, &odp_key, NULL);
    1431         [ +  + ]:       1180 :     if (error) {
    1432                 :          6 :         ofpbuf_uninit(&odp_key);
    1433                 :          6 :         return NULL;
    1434                 :            :     }
    1435                 :            : 
    1436                 :            :     /* Convert odp_key to flow. */
    1437                 :       1174 :     fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
    1438         [ -  + ]:       1174 :     if (fitness == ODP_FIT_ERROR) {
    1439                 :          0 :         ofpbuf_uninit(&odp_key);
    1440                 :          0 :         return NULL;
    1441                 :            :     }
    1442                 :            : 
    1443                 :       1174 :     packet = dp_packet_new(0);
    1444                 :       1174 :     flow_compose(packet, &flow);
    1445                 :            : 
    1446                 :       1174 :     ofpbuf_uninit(&odp_key);
    1447                 :       3903 :     return packet;
    1448                 :            : }
    1449                 :            : 
    1450                 :            : static void
    1451                 :       8619 : netdev_dummy_queue_packet__(struct netdev_rxq_dummy *rx, struct dp_packet *packet)
    1452                 :            : {
    1453                 :       8619 :     struct pkt_list_node *pkt_node = xmalloc(sizeof *pkt_node);
    1454                 :            : 
    1455                 :       8619 :     pkt_node->pkt = packet;
    1456                 :       8619 :     ovs_list_push_back(&rx->recv_queue, &pkt_node->list_node);
    1457                 :       8619 :     rx->recv_queue_len++;
    1458                 :       8619 :     seq_change(rx->seq);
    1459                 :       8619 : }
    1460                 :            : 
    1461                 :            : static void
    1462                 :       8619 : netdev_dummy_queue_packet(struct netdev_dummy *dummy, struct dp_packet *packet,
    1463                 :            :                           int queue_id)
    1464                 :            :     OVS_REQUIRES(dummy->mutex)
    1465                 :            : {
    1466                 :            :     struct netdev_rxq_dummy *rx, *prev;
    1467                 :            : 
    1468         [ +  + ]:       8619 :     if (dummy->rxq_pcap) {
    1469                 :       6738 :         ovs_pcap_write(dummy->rxq_pcap, packet);
    1470                 :       6738 :         fflush(dummy->rxq_pcap);
    1471                 :            :     }
    1472                 :       8619 :     prev = NULL;
    1473         [ +  + ]:      17308 :     LIST_FOR_EACH (rx, node, &dummy->rxes) {
    1474 [ +  + ][ +  - ]:       8689 :         if (rx->up.queue_id == queue_id &&
    1475                 :       8619 :             rx->recv_queue_len < NETDEV_DUMMY_MAX_QUEUE) {
    1476         [ -  + ]:       8619 :             if (prev) {
    1477                 :          0 :                 netdev_dummy_queue_packet__(prev, dp_packet_clone(packet));
    1478                 :            :             }
    1479                 :       8619 :             prev = rx;
    1480                 :            :         }
    1481                 :            :     }
    1482         [ +  - ]:       8619 :     if (prev) {
    1483                 :       8619 :         netdev_dummy_queue_packet__(prev, packet);
    1484                 :            :     } else {
    1485                 :          0 :         dp_packet_delete(packet);
    1486                 :            :     }
    1487                 :       8619 : }
    1488                 :            : 
    1489                 :            : static void
    1490                 :       3903 : netdev_dummy_receive(struct unixctl_conn *conn,
    1491                 :            :                      int argc, const char *argv[], void *aux OVS_UNUSED)
    1492                 :            : {
    1493                 :            :     struct netdev_dummy *dummy_dev;
    1494                 :            :     struct netdev *netdev;
    1495                 :       3903 :     int i, k = 1, rx_qid = 0;
    1496                 :            : 
    1497                 :       3903 :     netdev = netdev_from_name(argv[k++]);
    1498 [ +  - ][ -  + ]:       3903 :     if (!netdev || !is_dummy_class(netdev->netdev_class)) {
    1499                 :          0 :         unixctl_command_reply_error(conn, "no such dummy netdev");
    1500                 :          0 :         goto exit_netdev;
    1501                 :            :     }
    1502                 :       3903 :     dummy_dev = netdev_dummy_cast(netdev);
    1503                 :            : 
    1504                 :       3903 :     ovs_mutex_lock(&dummy_dev->mutex);
    1505                 :            : 
    1506 [ +  + ][ +  - ]:       3903 :     if (argc > k + 1 && !strcmp(argv[k], "--qid")) {
    1507                 :         14 :         rx_qid = strtol(argv[k + 1], NULL, 10);
    1508 [ +  - ][ -  + ]:         14 :         if (rx_qid < 0 || rx_qid >= netdev->n_rxq) {
    1509                 :          0 :             unixctl_command_reply_error(conn, "bad rx queue id.");
    1510                 :          0 :             goto exit;
    1511                 :            :         }
    1512                 :         14 :         k += 2;
    1513                 :            :     }
    1514                 :            : 
    1515         [ +  + ]:       7800 :     for (i = k; i < argc; i++) {
    1516                 :            :         struct dp_packet *packet;
    1517                 :            : 
    1518                 :       3903 :         packet = eth_from_packet_or_flow(argv[i]);
    1519         [ +  + ]:       3903 :         if (!packet) {
    1520                 :          6 :             unixctl_command_reply_error(conn, "bad packet syntax");
    1521                 :          6 :             goto exit;
    1522                 :            :         }
    1523                 :            : 
    1524                 :       3897 :         netdev_dummy_queue_packet(dummy_dev, packet, rx_qid);
    1525                 :            :     }
    1526                 :            : 
    1527                 :       3897 :     unixctl_command_reply(conn, NULL);
    1528                 :            : 
    1529                 :            : exit:
    1530                 :       3903 :     ovs_mutex_unlock(&dummy_dev->mutex);
    1531                 :            : exit_netdev:
    1532                 :       3903 :     netdev_close(netdev);
    1533                 :       3903 : }
    1534                 :            : 
    1535                 :            : static void
    1536                 :         66 : netdev_dummy_set_admin_state__(struct netdev_dummy *dev, bool admin_state)
    1537                 :            :     OVS_REQUIRES(dev->mutex)
    1538                 :            : {
    1539                 :            :     enum netdev_flags old_flags;
    1540                 :            : 
    1541         [ +  + ]:         66 :     if (admin_state) {
    1542                 :         64 :         netdev_dummy_update_flags__(dev, 0, NETDEV_UP, &old_flags);
    1543                 :            :     } else {
    1544                 :          2 :         netdev_dummy_update_flags__(dev, NETDEV_UP, 0, &old_flags);
    1545                 :            :     }
    1546                 :         66 : }
    1547                 :            : 
    1548                 :            : static void
    1549                 :         14 : netdev_dummy_set_admin_state(struct unixctl_conn *conn, int argc,
    1550                 :            :                              const char *argv[], void *aux OVS_UNUSED)
    1551                 :            : {
    1552                 :            :     bool up;
    1553                 :            : 
    1554         [ +  + ]:         14 :     if (!strcasecmp(argv[argc - 1], "up")) {
    1555                 :         12 :         up = true;
    1556         [ +  - ]:          2 :     } else if ( !strcasecmp(argv[argc - 1], "down")) {
    1557                 :          2 :         up = false;
    1558                 :            :     } else {
    1559                 :          0 :         unixctl_command_reply_error(conn, "Invalid Admin State");
    1560                 :          0 :         return;
    1561                 :            :     }
    1562                 :            : 
    1563         [ +  + ]:         14 :     if (argc > 2) {
    1564                 :          5 :         struct netdev *netdev = netdev_from_name(argv[1]);
    1565 [ +  - ][ +  - ]:         10 :         if (netdev && is_dummy_class(netdev->netdev_class)) {
    1566                 :          5 :             struct netdev_dummy *dummy_dev = netdev_dummy_cast(netdev);
    1567                 :            : 
    1568                 :          5 :             ovs_mutex_lock(&dummy_dev->mutex);
    1569                 :          5 :             netdev_dummy_set_admin_state__(dummy_dev, up);
    1570                 :          5 :             ovs_mutex_unlock(&dummy_dev->mutex);
    1571                 :            : 
    1572                 :          5 :             netdev_close(netdev);
    1573                 :            :         } else {
    1574                 :          0 :             unixctl_command_reply_error(conn, "Unknown Dummy Interface");
    1575                 :          0 :             netdev_close(netdev);
    1576                 :          0 :             return;
    1577                 :            :         }
    1578                 :            :     } else {
    1579                 :            :         struct netdev_dummy *netdev;
    1580                 :            : 
    1581                 :          9 :         ovs_mutex_lock(&dummy_list_mutex);
    1582         [ +  + ]:         70 :         LIST_FOR_EACH (netdev, list_node, &dummy_list) {
    1583                 :         61 :             ovs_mutex_lock(&netdev->mutex);
    1584                 :         61 :             netdev_dummy_set_admin_state__(netdev, up);
    1585                 :         61 :             ovs_mutex_unlock(&netdev->mutex);
    1586                 :            :         }
    1587                 :          9 :         ovs_mutex_unlock(&dummy_list_mutex);
    1588                 :            :     }
    1589                 :         14 :     unixctl_command_reply(conn, "OK");
    1590                 :            : }
    1591                 :            : 
    1592                 :            : static void
    1593                 :          5 : display_conn_state__(struct ds *s, const char *name,
    1594                 :            :                      enum dummy_netdev_conn_state state)
    1595                 :            : {
    1596                 :          5 :     ds_put_format(s, "%s: ", name);
    1597                 :            : 
    1598      [ +  -  - ]:          5 :     switch (state) {
    1599                 :            :     case CONN_STATE_CONNECTED:
    1600                 :          5 :         ds_put_cstr(s, "connected\n");
    1601                 :          5 :         break;
    1602                 :            : 
    1603                 :            :     case CONN_STATE_NOT_CONNECTED:
    1604                 :          0 :         ds_put_cstr(s, "disconnected\n");
    1605                 :          0 :         break;
    1606                 :            : 
    1607                 :            :     case CONN_STATE_UNKNOWN:
    1608                 :            :     default:
    1609                 :          0 :         ds_put_cstr(s, "unknown\n");
    1610                 :          0 :         break;
    1611                 :            :     };
    1612                 :          5 : }
    1613                 :            : 
    1614                 :            : static void
    1615                 :          5 : netdev_dummy_conn_state(struct unixctl_conn *conn, int argc,
    1616                 :            :                         const char *argv[], void *aux OVS_UNUSED)
    1617                 :            : {
    1618                 :          5 :     enum dummy_netdev_conn_state state = CONN_STATE_UNKNOWN;
    1619                 :            :     struct ds s;
    1620                 :            : 
    1621                 :          5 :     ds_init(&s);
    1622                 :            : 
    1623         [ +  - ]:          5 :     if (argc > 1) {
    1624                 :          5 :         const char *dev_name = argv[1];
    1625                 :          5 :         struct netdev *netdev = netdev_from_name(dev_name);
    1626                 :            : 
    1627 [ +  - ][ +  - ]:          5 :         if (netdev && is_dummy_class(netdev->netdev_class)) {
    1628                 :          5 :             struct netdev_dummy *dummy_dev = netdev_dummy_cast(netdev);
    1629                 :            : 
    1630                 :          5 :             ovs_mutex_lock(&dummy_dev->mutex);
    1631                 :          5 :             state = dummy_netdev_get_conn_state(&dummy_dev->conn);
    1632                 :          5 :             ovs_mutex_unlock(&dummy_dev->mutex);
    1633                 :            : 
    1634                 :          5 :             netdev_close(netdev);
    1635                 :            :         }
    1636                 :          5 :         display_conn_state__(&s, dev_name, state);
    1637                 :            :     } else {
    1638                 :            :         struct netdev_dummy *netdev;
    1639                 :            : 
    1640                 :          0 :         ovs_mutex_lock(&dummy_list_mutex);
    1641         [ #  # ]:          0 :         LIST_FOR_EACH (netdev, list_node, &dummy_list) {
    1642                 :          0 :             ovs_mutex_lock(&netdev->mutex);
    1643                 :          0 :             state = dummy_netdev_get_conn_state(&netdev->conn);
    1644                 :          0 :             ovs_mutex_unlock(&netdev->mutex);
    1645         [ #  # ]:          0 :             if (state != CONN_STATE_UNKNOWN) {
    1646                 :          0 :                 display_conn_state__(&s, netdev->up.name, state);
    1647                 :            :             }
    1648                 :            :         }
    1649                 :          0 :         ovs_mutex_unlock(&dummy_list_mutex);
    1650                 :            :     }
    1651                 :            : 
    1652                 :          5 :     unixctl_command_reply(conn, ds_cstr(&s));
    1653                 :          5 :     ds_destroy(&s);
    1654                 :          5 : }
    1655                 :            : 
    1656                 :            : static void
    1657                 :         45 : netdev_dummy_ip4addr(struct unixctl_conn *conn, int argc OVS_UNUSED,
    1658                 :            :                      const char *argv[], void *aux OVS_UNUSED)
    1659                 :            : {
    1660                 :         45 :     struct netdev *netdev = netdev_from_name(argv[1]);
    1661                 :            : 
    1662 [ +  - ][ +  - ]:         90 :     if (netdev && is_dummy_class(netdev->netdev_class)) {
    1663                 :            :         struct in_addr ip, mask;
    1664                 :            :         char *error;
    1665                 :            : 
    1666                 :         45 :         error = ip_parse_masked(argv[2], &ip.s_addr, &mask.s_addr);
    1667         [ +  - ]:         45 :         if (!error) {
    1668                 :         45 :             netdev_dummy_set_in4(netdev, ip, mask);
    1669                 :         45 :             unixctl_command_reply(conn, "OK");
    1670                 :            :         } else {
    1671                 :          0 :             unixctl_command_reply_error(conn, error);
    1672                 :          0 :             free(error);
    1673                 :            :         }
    1674                 :            :     } else {
    1675                 :          0 :         unixctl_command_reply_error(conn, "Unknown Dummy Interface");
    1676                 :            :     }
    1677                 :            : 
    1678                 :         45 :     netdev_close(netdev);
    1679                 :         45 : }
    1680                 :            : 
    1681                 :            : static void
    1682                 :          2 : netdev_dummy_ip6addr(struct unixctl_conn *conn, int argc OVS_UNUSED,
    1683                 :            :                      const char *argv[], void *aux OVS_UNUSED)
    1684                 :            : {
    1685                 :          2 :     struct netdev *netdev = netdev_from_name(argv[1]);
    1686                 :            : 
    1687 [ +  - ][ +  - ]:          4 :     if (netdev && is_dummy_class(netdev->netdev_class)) {
    1688                 :            :         struct in6_addr ip6;
    1689                 :            :         char *error;
    1690                 :            :         uint32_t plen;
    1691                 :            : 
    1692                 :          2 :         error = ipv6_parse_cidr(argv[2], &ip6, &plen);
    1693         [ +  - ]:          2 :         if (!error) {
    1694                 :            :             struct in6_addr mask;
    1695                 :            : 
    1696                 :          2 :             mask = ipv6_create_mask(plen);
    1697                 :          2 :             netdev_dummy_set_in6(netdev, &ip6, &mask);
    1698                 :          2 :             unixctl_command_reply(conn, "OK");
    1699                 :            :         } else {
    1700                 :          0 :             unixctl_command_reply_error(conn, error);
    1701                 :          0 :             free(error);
    1702                 :            :         }
    1703                 :          2 :         netdev_close(netdev);
    1704                 :            :     } else {
    1705                 :          0 :         unixctl_command_reply_error(conn, "Unknown Dummy Interface");
    1706                 :            :     }
    1707                 :            : 
    1708                 :          2 :     netdev_close(netdev);
    1709                 :          2 : }
    1710                 :            : 
    1711                 :            : 
    1712                 :            : static void
    1713                 :         90 : netdev_dummy_override(const char *type)
    1714                 :            : {
    1715         [ +  - ]:         90 :     if (!netdev_unregister_provider(type)) {
    1716                 :            :         struct netdev_class *class;
    1717                 :            :         int error;
    1718                 :            : 
    1719                 :         90 :         class = xmemdup(&dummy_class, sizeof dummy_class);
    1720                 :         90 :         class->type = xstrdup(type);
    1721                 :         90 :         error = netdev_register_provider(class);
    1722         [ -  + ]:         90 :         if (error) {
    1723         [ #  # ]:          0 :             VLOG_ERR("%s: failed to register netdev provider (%s)",
    1724                 :            :                      type, ovs_strerror(error));
    1725                 :          0 :             free(CONST_CAST(char *, class->type));
    1726                 :          0 :             free(class);
    1727                 :            :         }
    1728                 :            :     }
    1729                 :         90 : }
    1730                 :            : 
    1731                 :            : void
    1732                 :        543 : netdev_dummy_register(enum dummy_level level)
    1733                 :            : {
    1734                 :        543 :     unixctl_command_register("netdev-dummy/receive",
    1735                 :            :                              "name [--qid queue_id] packet|flow...",
    1736                 :            :                              2, INT_MAX, netdev_dummy_receive, NULL);
    1737                 :        543 :     unixctl_command_register("netdev-dummy/set-admin-state",
    1738                 :            :                              "[netdev] up|down", 1, 2,
    1739                 :            :                              netdev_dummy_set_admin_state, NULL);
    1740                 :        543 :     unixctl_command_register("netdev-dummy/conn-state",
    1741                 :            :                              "[netdev]", 0, 1,
    1742                 :            :                              netdev_dummy_conn_state, NULL);
    1743                 :        543 :     unixctl_command_register("netdev-dummy/ip4addr",
    1744                 :            :                              "[netdev] ipaddr/mask-prefix-len", 2, 2,
    1745                 :            :                              netdev_dummy_ip4addr, NULL);
    1746                 :        543 :     unixctl_command_register("netdev-dummy/ip6addr",
    1747                 :            :                              "[netdev] ip6addr", 2, 2,
    1748                 :            :                              netdev_dummy_ip6addr, NULL);
    1749                 :            : 
    1750         [ +  + ]:        543 :     if (level == DUMMY_OVERRIDE_ALL) {
    1751                 :            :         struct sset types;
    1752                 :            :         const char *type;
    1753                 :            : 
    1754                 :          1 :         sset_init(&types);
    1755                 :          1 :         netdev_enumerate_types(&types);
    1756 [ +  - ][ +  + ]:         11 :         SSET_FOR_EACH (type, &types) {
                 [ +  + ]
    1757         [ +  + ]:         10 :             if (strcmp(type, "patch")) {
    1758                 :          9 :                 netdev_dummy_override(type);
    1759                 :            :             }
    1760                 :            :         }
    1761                 :          1 :         sset_destroy(&types);
    1762         [ +  + ]:        542 :     } else if (level == DUMMY_OVERRIDE_SYSTEM) {
    1763                 :         81 :         netdev_dummy_override("system");
    1764                 :            :     }
    1765                 :        543 :     netdev_register_provider(&dummy_class);
    1766                 :        543 :     netdev_register_provider(&dummy_internal_class);
    1767                 :        543 :     netdev_register_provider(&dummy_pmd_class);
    1768                 :            : 
    1769                 :        543 :     netdev_vport_tunnel_register();
    1770                 :        543 : }

Generated by: LCOV version 1.12