LCOV - code coverage report
Current view: top level - tests - test-stp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 237 336 70.5 %
Date: 2016-09-14 01:02:56 Functions: 15 21 71.4 %
Branches: 146 222 65.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2014 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                 :            : #undef NDEBUG
      19                 :            : #include "stp.h"
      20                 :            : #include <assert.h>
      21                 :            : #include <ctype.h>
      22                 :            : #include <errno.h>
      23                 :            : #include <inttypes.h>
      24                 :            : #include <stdarg.h>
      25                 :            : #include <stdlib.h>
      26                 :            : #include "dp-packet.h"
      27                 :            : #include "openvswitch/ofpbuf.h"
      28                 :            : #include "ovstest.h"
      29                 :            : #include "packets.h"
      30                 :            : #include "openvswitch/vlog.h"
      31                 :            : 
      32                 :            : struct bpdu {
      33                 :            :     int port_no;
      34                 :            :     void *data;
      35                 :            :     size_t size;
      36                 :            : };
      37                 :            : 
      38                 :            : struct bridge {
      39                 :            :     struct test_case *tc;
      40                 :            :     int id;
      41                 :            :     bool reached;
      42                 :            : 
      43                 :            :     struct stp *stp;
      44                 :            : 
      45                 :            :     struct lan *ports[STP_MAX_PORTS];
      46                 :            :     int n_ports;
      47                 :            : 
      48                 :            : #define RXQ_SIZE 16
      49                 :            :     struct bpdu rxq[RXQ_SIZE];
      50                 :            :     int rxq_head, rxq_tail;
      51                 :            : };
      52                 :            : 
      53                 :            : struct lan_conn {
      54                 :            :     struct bridge *bridge;
      55                 :            :     int port_no;
      56                 :            : };
      57                 :            : 
      58                 :            : struct lan {
      59                 :            :     struct test_case *tc;
      60                 :            :     const char *name;
      61                 :            :     bool reached;
      62                 :            :     struct lan_conn conns[16];
      63                 :            :     int n_conns;
      64                 :            : };
      65                 :            : 
      66                 :            : struct test_case {
      67                 :            :     struct bridge *bridges[16];
      68                 :            :     int n_bridges;
      69                 :            :     struct lan *lans[26];
      70                 :            :     int n_lans;
      71                 :            : };
      72                 :            : 
      73                 :            : static const char *file_name;
      74                 :            : static int line_number;
      75                 :            : static char line[128];
      76                 :            : static char *pos, *token;
      77                 :            : static int n_warnings;
      78                 :            : 
      79                 :            : static struct test_case *
      80                 :         13 : new_test_case(void)
      81                 :            : {
      82                 :         13 :     struct test_case *tc = xmalloc(sizeof *tc);
      83                 :         13 :     tc->n_bridges = 0;
      84                 :         13 :     tc->n_lans = 0;
      85                 :         13 :     return tc;
      86                 :            : }
      87                 :            : 
      88                 :            : static void
      89                 :      15236 : send_bpdu(struct dp_packet *pkt, int port_no, void *b_)
      90                 :            : {
      91                 :      15236 :     struct bridge *b = b_;
      92                 :            :     struct lan *lan;
      93                 :            : 
      94         [ -  + ]:      15236 :     assert(port_no < b->n_ports);
      95                 :      15236 :     lan = b->ports[port_no];
      96         [ +  + ]:      15236 :     if (lan) {
      97                 :      13774 :         const void *data = dp_packet_l3(pkt);
      98                 :      13774 :         size_t size = (char *) dp_packet_tail(pkt) - (char *) data;
      99                 :            :         int i;
     100                 :            : 
     101         [ +  + ]:      38130 :         for (i = 0; i < lan->n_conns; i++) {
     102                 :      24356 :             struct lan_conn *conn = &lan->conns[i];
     103 [ +  + ][ +  + ]:      24356 :             if (conn->bridge != b || conn->port_no != port_no) {
     104                 :      10582 :                 struct bridge *dst = conn->bridge;
     105                 :      10582 :                 struct bpdu *bpdu = &dst->rxq[dst->rxq_head++ % RXQ_SIZE];
     106         [ -  + ]:      10582 :                 assert(dst->rxq_head - dst->rxq_tail <= RXQ_SIZE);
     107                 :      10582 :                 bpdu->data = xmemdup(data, size);
     108                 :      10582 :                 bpdu->size = size;
     109                 :      10582 :                 bpdu->port_no = conn->port_no;
     110                 :            :             }
     111                 :            :         }
     112                 :            :     }
     113                 :      15236 :     dp_packet_delete(pkt);
     114                 :      15236 : }
     115                 :            : 
     116                 :            : static struct bridge *
     117                 :         44 : new_bridge(struct test_case *tc, int id)
     118                 :            : {
     119                 :         44 :     struct bridge *b = xmalloc(sizeof *b);
     120                 :            :     char name[16];
     121                 :         44 :     b->tc = tc;
     122                 :         44 :     b->id = id;
     123                 :         44 :     snprintf(name, sizeof name, "stp%x", id);
     124                 :         44 :     b->stp = stp_create(name, id, send_bpdu, b);
     125         [ -  + ]:         44 :     assert(tc->n_bridges < ARRAY_SIZE(tc->bridges));
     126                 :         44 :     b->n_ports = 0;
     127                 :         44 :     b->rxq_head = b->rxq_tail = 0;
     128                 :         44 :     tc->bridges[tc->n_bridges++] = b;
     129                 :         44 :     return b;
     130                 :            : }
     131                 :            : 
     132                 :            : static struct lan *
     133                 :        338 : new_lan(struct test_case *tc, const char *name)
     134                 :            : {
     135                 :        338 :     struct lan *lan = xmalloc(sizeof *lan);
     136                 :        338 :     lan->tc = tc;
     137                 :        338 :     lan->name = xstrdup(name);
     138                 :        338 :     lan->n_conns = 0;
     139         [ -  + ]:        338 :     assert(tc->n_lans < ARRAY_SIZE(tc->lans));
     140                 :        338 :     tc->lans[tc->n_lans++] = lan;
     141                 :        338 :     return lan;
     142                 :            : }
     143                 :            : 
     144                 :            : static void
     145                 :        150 : reconnect_port(struct bridge *b, int port_no, struct lan *new_lan)
     146                 :            : {
     147                 :            :     struct lan *old_lan;
     148                 :            :     int j;
     149                 :            : 
     150         [ -  + ]:        150 :     assert(port_no < b->n_ports);
     151                 :        150 :     old_lan = b->ports[port_no];
     152         [ +  + ]:        150 :     if (old_lan == new_lan) {
     153                 :         18 :         return;
     154                 :            :     }
     155                 :            : 
     156                 :            :     /* Disconnect from old_lan. */
     157         [ +  + ]:        132 :     if (old_lan) {
     158         [ +  - ]:          4 :         for (j = 0; j < old_lan->n_conns; j++) {
     159                 :          4 :             struct lan_conn *c = &old_lan->conns[j];
     160 [ +  + ][ +  - ]:          4 :             if (c->bridge == b && c->port_no == port_no) {
     161                 :          2 :                 memmove(c, c + 1, sizeof *c * (old_lan->n_conns - j - 1));
     162                 :          2 :                 old_lan->n_conns--;
     163                 :          2 :                 break;
     164                 :            :             }
     165                 :            :         }
     166                 :            :     }
     167                 :            : 
     168                 :            :     /* Connect to new_lan. */
     169                 :        132 :     b->ports[port_no] = new_lan;
     170         [ +  + ]:        132 :     if (new_lan) {
     171                 :        130 :         int conn_no = new_lan->n_conns++;
     172         [ -  + ]:        130 :         assert(conn_no < ARRAY_SIZE(new_lan->conns));
     173                 :        130 :         new_lan->conns[conn_no].bridge = b;
     174                 :        130 :         new_lan->conns[conn_no].port_no = port_no;
     175                 :            :     }
     176                 :            : }
     177                 :            : 
     178                 :            : static void
     179                 :        136 : new_port(struct bridge *b, struct lan *lan, int path_cost)
     180                 :            : {
     181                 :        136 :     int port_no = b->n_ports++;
     182                 :        136 :     struct stp_port *p = stp_get_port(b->stp, port_no);
     183         [ -  + ]:        136 :     assert(port_no < ARRAY_SIZE(b->ports));
     184                 :        136 :     b->ports[port_no] = NULL;
     185                 :        136 :     stp_port_set_path_cost(p, path_cost);
     186                 :        136 :     stp_port_enable(p);
     187                 :        136 :     reconnect_port(b, port_no, lan);
     188                 :        136 : }
     189                 :            : 
     190                 :            : static void
     191                 :          0 : dump(struct test_case *tc)
     192                 :            : {
     193                 :            :     int i;
     194                 :            : 
     195         [ #  # ]:          0 :     for (i = 0; i < tc->n_bridges; i++) {
     196                 :          0 :         struct bridge *b = tc->bridges[i];
     197                 :          0 :         struct stp *stp = b->stp;
     198                 :            :         int j;
     199                 :            : 
     200                 :          0 :         printf("%s:", stp_get_name(stp));
     201         [ #  # ]:          0 :         if (stp_is_root_bridge(stp)) {
     202                 :          0 :             printf(" root");
     203                 :            :         }
     204                 :          0 :         printf("\n");
     205         [ #  # ]:          0 :         for (j = 0; j < b->n_ports; j++) {
     206                 :          0 :             struct stp_port *p = stp_get_port(stp, j);
     207                 :          0 :             enum stp_state state = stp_port_get_state(p);
     208                 :            : 
     209                 :          0 :             printf("\tport %d", j);
     210         [ #  # ]:          0 :             if (b->ports[j]) {
     211                 :          0 :                 printf(" (lan %s)", b->ports[j]->name);
     212                 :            :             } else {
     213                 :          0 :                 printf(" (disconnected)");
     214                 :            :             }
     215                 :          0 :             printf(": %s", stp_state_name(state));
     216         [ #  # ]:          0 :             if (p == stp_get_root_port(stp)) {
     217                 :          0 :                 printf(" (root port, root_path_cost=%u)", stp_get_root_path_cost(stp));
     218                 :            :             }
     219                 :          0 :             printf("\n");
     220                 :            :         }
     221                 :            :     }
     222                 :          0 : }
     223                 :            : 
     224                 :            : static void dump_lan_tree(struct test_case *, struct lan *, int level);
     225                 :            : 
     226                 :            : static void
     227                 :          0 : dump_bridge_tree(struct test_case *tc, struct bridge *b, int level)
     228                 :            : {
     229                 :            :     int i;
     230                 :            : 
     231         [ #  # ]:          0 :     if (b->reached) {
     232                 :          0 :         return;
     233                 :            :     }
     234                 :          0 :     b->reached = true;
     235         [ #  # ]:          0 :     for (i = 0; i < level; i++) {
     236                 :          0 :         printf("\t");
     237                 :            :     }
     238                 :          0 :     printf("%s\n", stp_get_name(b->stp));
     239         [ #  # ]:          0 :     for (i = 0; i < b->n_ports; i++) {
     240                 :          0 :         struct lan *lan = b->ports[i];
     241                 :          0 :         struct stp_port *p = stp_get_port(b->stp, i);
     242 [ #  # ][ #  # ]:          0 :         if (stp_port_get_state(p) == STP_FORWARDING && lan) {
     243                 :          0 :             dump_lan_tree(tc, lan, level + 1);
     244                 :            :         }
     245                 :            :     }
     246                 :            : }
     247                 :            : 
     248                 :            : static void
     249                 :          0 : dump_lan_tree(struct test_case *tc, struct lan *lan, int level)
     250                 :            : {
     251                 :            :     int i;
     252                 :            : 
     253         [ #  # ]:          0 :     if (lan->reached) {
     254                 :          0 :         return;
     255                 :            :     }
     256                 :          0 :     lan->reached = true;
     257         [ #  # ]:          0 :     for (i = 0; i < level; i++) {
     258                 :          0 :         printf("\t");
     259                 :            :     }
     260                 :          0 :     printf("%s\n", lan->name);
     261         [ #  # ]:          0 :     for (i = 0; i < lan->n_conns; i++) {
     262                 :          0 :         struct bridge *b = lan->conns[i].bridge;
     263                 :          0 :         dump_bridge_tree(tc, b, level + 1);
     264                 :            :     }
     265                 :            : }
     266                 :            : 
     267                 :            : static void
     268                 :          0 : tree(struct test_case *tc)
     269                 :            : {
     270                 :            :     int i;
     271                 :            : 
     272         [ #  # ]:          0 :     for (i = 0; i < tc->n_bridges; i++) {
     273                 :          0 :         struct bridge *b = tc->bridges[i];
     274                 :          0 :         b->reached = false;
     275                 :            :     }
     276         [ #  # ]:          0 :     for (i = 0; i < tc->n_lans; i++) {
     277                 :          0 :         struct lan *lan = tc->lans[i];
     278                 :          0 :         lan->reached = false;
     279                 :            :     }
     280         [ #  # ]:          0 :     for (i = 0; i < tc->n_bridges; i++) {
     281                 :          0 :         struct bridge *b = tc->bridges[i];
     282                 :          0 :         struct stp *stp = b->stp;
     283         [ #  # ]:          0 :         if (stp_is_root_bridge(stp)) {
     284                 :          0 :             dump_bridge_tree(tc, b, 0);
     285                 :            :         }
     286                 :            :     }
     287                 :          0 : }
     288                 :            : 
     289                 :            : static void
     290                 :         23 : simulate(struct test_case *tc, int granularity)
     291                 :            : {
     292                 :            :     int time;
     293                 :            : 
     294         [ +  + ]:       4163 :     for (time = 0; time < 1000 * 180; time += granularity) {
     295                 :            :         int round_trips;
     296                 :            :         int i;
     297                 :            : 
     298         [ +  + ]:      18540 :         for (i = 0; i < tc->n_bridges; i++) {
     299                 :      14400 :             stp_tick(tc->bridges[i]->stp, granularity);
     300                 :            :         }
     301         [ +  - ]:       6898 :         for (round_trips = 0; round_trips < granularity; round_trips++) {
     302                 :       6898 :             bool any = false;
     303         [ +  + ]:      31811 :             for (i = 0; i < tc->n_bridges; i++) {
     304                 :      24913 :                 struct bridge *b = tc->bridges[i];
     305         [ +  + ]:      35495 :                 for (; b->rxq_tail != b->rxq_head; b->rxq_tail++) {
     306                 :      10582 :                     struct bpdu *bpdu = &b->rxq[b->rxq_tail % RXQ_SIZE];
     307                 :      10582 :                     stp_received_bpdu(stp_get_port(b->stp, bpdu->port_no),
     308                 :      10582 :                                       bpdu->data, bpdu->size);
     309                 :      10582 :                     free(bpdu->data);
     310                 :      10582 :                     any = true;
     311                 :            :                 }
     312                 :            :             }
     313         [ +  + ]:       6898 :             if (!any) {
     314                 :       4140 :                 break;
     315                 :            :             }
     316                 :            :         }
     317                 :            :     }
     318                 :         23 : }
     319                 :            : 
     320                 :            : OVS_NO_RETURN static void
     321                 :            : err(const char *message, ...)
     322                 :            :     OVS_PRINTF_FORMAT(1, 2);
     323                 :            : 
     324                 :            : static void
     325                 :          0 : err(const char *message, ...)
     326                 :            : {
     327                 :            :     va_list args;
     328                 :            : 
     329                 :          0 :     fprintf(stderr, "%s:%d:%"PRIdPTR": ", file_name, line_number, pos - line);
     330                 :          0 :     va_start(args, message);
     331                 :          0 :     vfprintf(stderr, message, args);
     332                 :          0 :     va_end(args);
     333                 :          0 :     putc('\n', stderr);
     334                 :            : 
     335                 :          0 :     exit(EXIT_FAILURE);
     336                 :            : }
     337                 :            : 
     338                 :            : static void
     339                 :            : warn(const char *message, ...)
     340                 :            :     OVS_PRINTF_FORMAT(1, 2);
     341                 :            : 
     342                 :            : static void
     343                 :          0 : warn(const char *message, ...)
     344                 :            : {
     345                 :            :     va_list args;
     346                 :            : 
     347                 :          0 :     fprintf(stderr, "%s:%d: ", file_name, line_number);
     348                 :          0 :     va_start(args, message);
     349                 :          0 :     vfprintf(stderr, message, args);
     350                 :          0 :     va_end(args);
     351                 :          0 :     putc('\n', stderr);
     352                 :            : 
     353                 :          0 :     n_warnings++;
     354                 :          0 : }
     355                 :            : 
     356                 :            : static bool
     357                 :       1504 : get_token(void)
     358                 :            : {
     359                 :            :     char *start;
     360                 :            : 
     361         [ +  + ]:       2278 :     while (isspace((unsigned char) *pos)) {
     362                 :        774 :         pos++;
     363                 :            :     }
     364         [ +  + ]:       1504 :     if (*pos == '\0') {
     365                 :        375 :         free(token);
     366                 :        375 :         token = NULL;
     367                 :        375 :         return false;
     368                 :            :     }
     369                 :            : 
     370                 :       1129 :     start = pos;
     371         [ +  + ]:       1129 :     if (isalpha((unsigned char) *pos)) {
     372         [ +  + ]:       1389 :         while (isalpha((unsigned char) *++pos)) {
     373                 :        813 :             continue;
     374                 :            :         }
     375         [ +  + ]:        553 :     } else if (isdigit((unsigned char) *pos)) {
     376 [ +  + ][ +  + ]:        390 :         if (*pos == '0' && (pos[1] == 'x' || pos[1] == 'X')) {
                 [ -  + ]
     377                 :         76 :             pos += 2;
     378         [ +  + ]:        314 :             while (isxdigit((unsigned char) *pos)) {
     379                 :        238 :                 pos++;
     380                 :            :             }
     381                 :            :         } else {
     382         [ +  + ]:        438 :             while (isdigit((unsigned char) *++pos)) {
     383                 :        124 :                 continue;
     384                 :            :             }
     385                 :            :         }
     386                 :            :     } else {
     387                 :        239 :         pos++;
     388                 :            :     }
     389                 :            : 
     390                 :       1129 :     free(token);
     391                 :       1129 :     token = xmemdup0(start, pos - start);
     392                 :       1129 :     return true;
     393                 :            : }
     394                 :            : 
     395                 :            : static bool
     396                 :        304 : get_int(int *intp)
     397                 :            : {
     398                 :        304 :     char *save_pos = pos;
     399 [ +  - ][ +  - ]:        304 :     if (token && isdigit((unsigned char) *token)) {
     400                 :        304 :         *intp = strtol(token, NULL, 0);
     401                 :        304 :         get_token();
     402                 :        304 :         return true;
     403                 :            :     } else {
     404                 :          0 :         pos = save_pos;
     405                 :          0 :         return false;
     406                 :            :     }
     407                 :            : }
     408                 :            : 
     409                 :            : static bool
     410                 :       2670 : match(const char *want)
     411                 :            : {
     412 [ +  + ][ +  + ]:       2670 :     if (token && !strcmp(want, token)) {
     413                 :        675 :         get_token();
     414                 :        675 :         return true;
     415                 :            :     } else {
     416                 :       1995 :         return false;
     417                 :            :     }
     418                 :            : }
     419                 :            : 
     420                 :            : static int
     421                 :        304 : must_get_int(void)
     422                 :            : {
     423                 :            :     int x;
     424         [ -  + ]:        304 :     if (!get_int(&x)) {
     425                 :          0 :         err("expected integer");
     426                 :            :     }
     427                 :        304 :     return x;
     428                 :            : }
     429                 :            : 
     430                 :            : static void
     431                 :         98 : must_match(const char *want)
     432                 :            : {
     433         [ -  + ]:         98 :     if (!match(want)) {
     434                 :          0 :         err("expected \"%s\"", want);
     435                 :            :     }
     436                 :         98 : }
     437                 :            : 
     438                 :            : static void
     439                 :         13 : test_stp_main(int argc, char *argv[])
     440                 :            : {
     441                 :            :     struct test_case *tc;
     442                 :            :     FILE *input_file;
     443                 :            :     int i;
     444                 :            : 
     445                 :         13 :     vlog_set_pattern(VLF_CONSOLE, "%c|%p|%m");
     446                 :         13 :     vlog_set_levels(NULL, VLF_SYSLOG, VLL_OFF);
     447                 :            : 
     448         [ -  + ]:         13 :     if (argc != 2) {
     449                 :          0 :         ovs_fatal(0, "usage: test-stp INPUT.STP\n");
     450                 :            :     }
     451                 :         13 :     file_name = argv[1];
     452                 :            : 
     453                 :         13 :     input_file = fopen(file_name, "r");
     454         [ -  + ]:         13 :     if (!input_file) {
     455                 :          0 :         ovs_fatal(errno, "error opening \"%s\"", file_name);
     456                 :            :     }
     457                 :            : 
     458                 :         13 :     tc = new_test_case();
     459         [ +  + ]:        351 :     for (i = 0; i < 26; i++) {
     460                 :            :         char name[2];
     461                 :        338 :         name[0] = 'a' + i;
     462                 :        338 :         name[1] = '\0';
     463                 :        338 :         new_lan(tc, name);
     464                 :            :     }
     465                 :            : 
     466         [ +  + ]:        223 :     for (line_number = 1; fgets(line, sizeof line, input_file);
     467                 :        210 :          line_number++)
     468                 :            :     {
     469                 :            :         char *newline, *hash;
     470                 :            : 
     471                 :        210 :         newline = strchr(line, '\n');
     472         [ +  - ]:        210 :         if (newline) {
     473                 :        210 :             *newline = '\0';
     474                 :            :         }
     475                 :        210 :         hash = strchr(line, '#');
     476         [ +  + ]:        210 :         if (hash) {
     477                 :         43 :             *hash = '\0';
     478                 :            :         }
     479                 :            : 
     480                 :        210 :         pos = line;
     481         [ +  + ]:        210 :         if (!get_token()) {
     482                 :         45 :             continue;
     483                 :            :         }
     484         [ +  + ]:        165 :         if (match("bridge")) {
     485                 :            :             struct bridge *bridge;
     486                 :            :             int bridge_no, port_no;
     487                 :            : 
     488                 :         58 :             bridge_no = must_get_int();
     489         [ +  + ]:         58 :             if (bridge_no < tc->n_bridges) {
     490                 :         14 :                 bridge = tc->bridges[bridge_no];
     491         [ +  - ]:         44 :             } else if (bridge_no == tc->n_bridges) {
     492                 :         44 :                 bridge = new_bridge(tc, must_get_int());
     493                 :            :             } else {
     494                 :          0 :                 err("bridges must be numbered consecutively from 0");
     495                 :            :             }
     496         [ +  + ]:         58 :             if (match("^")) {
     497                 :         11 :                 stp_set_bridge_priority(bridge->stp, must_get_int());
     498                 :            :             }
     499                 :            : 
     500         [ +  + ]:         58 :             if (match("=")) {
     501         [ +  + ]:      13063 :                 for (port_no = 0; port_no < STP_MAX_PORTS; port_no++) {
     502                 :      13005 :                     struct stp_port *p = stp_get_port(bridge->stp, port_no);
     503 [ +  + ][ +  + ]:      13005 :                     if (!token || match("X")) {
     504                 :      12846 :                         stp_port_disable(p);
     505         [ +  + ]:        159 :                     } else if (match("_")) {
     506                 :            :                         /* Nothing to do. */
     507                 :            :                     } else {
     508                 :            :                         struct lan *lan;
     509                 :            :                         int path_cost;
     510                 :            : 
     511         [ +  + ]:        150 :                         if (!strcmp(token, "0")) {
     512                 :         10 :                             lan = NULL;
     513         [ +  - ]:        140 :                         } else if (strlen(token) == 1
     514         [ +  - ]:        140 :                                 && islower((unsigned char)*token)) {
     515                 :        140 :                             lan = tc->lans[*token - 'a'];
     516                 :            :                         } else {
     517                 :          0 :                             err("%s is not a valid LAN name "
     518                 :            :                                 "(0 or a lowercase letter)", token);
     519                 :            :                         }
     520                 :        150 :                         get_token();
     521                 :            : 
     522         [ +  + ]:        150 :                         path_cost = match(":") ? must_get_int() : 10;
     523         [ +  + ]:        150 :                         if (port_no < bridge->n_ports) {
     524                 :         14 :                             stp_port_set_path_cost(p, path_cost);
     525                 :         14 :                             stp_port_enable(p);
     526                 :         14 :                             reconnect_port(bridge, port_no, lan);
     527         [ +  - ]:        136 :                         } else if (port_no == bridge->n_ports) {
     528                 :        136 :                             new_port(bridge, lan, path_cost);
     529                 :            :                         } else {
     530                 :          0 :                             err("ports must be numbered consecutively");
     531                 :            :                         }
     532         [ +  + ]:        150 :                         if (match("^")) {
     533                 :          1 :                             stp_port_set_priority(p, must_get_int());
     534                 :            :                         }
     535                 :            :                     }
     536                 :            :                 }
     537                 :            :             }
     538         [ +  + ]:        107 :         } else if (match("run")) {
     539                 :         23 :             simulate(tc, must_get_int());
     540         [ -  + ]:         84 :         } else if (match("dump")) {
     541                 :          0 :             dump(tc);
     542         [ -  + ]:         84 :         } else if (match("tree")) {
     543                 :          0 :             tree(tc);
     544         [ +  - ]:         84 :         } else if (match("check")) {
     545                 :            :             struct bridge *b;
     546                 :            :             struct stp *stp;
     547                 :            :             int bridge_no, port_no;
     548                 :            : 
     549                 :         84 :             bridge_no = must_get_int();
     550         [ -  + ]:         84 :             if (bridge_no >= tc->n_bridges) {
     551                 :          0 :                 err("no bridge numbered %d", bridge_no);
     552                 :            :             }
     553                 :         84 :             b = tc->bridges[bridge_no];
     554                 :         84 :             stp = b->stp;
     555                 :            : 
     556                 :         84 :             must_match("=");
     557                 :            : 
     558         [ +  + ]:         84 :             if (match("rootid")) {
     559                 :            :                 uint64_t rootid;
     560                 :         14 :                 must_match(":");
     561                 :         14 :                 rootid = must_get_int();
     562         [ +  + ]:         14 :                 if (match("^")) {
     563                 :          6 :                     rootid |= (uint64_t) must_get_int() << 48;
     564                 :            :                 } else {
     565                 :          8 :                     rootid |= UINT64_C(0x8000) << 48;
     566                 :            :                 }
     567         [ -  + ]:         14 :                 if (stp_get_designated_root(stp) != rootid) {
     568                 :          0 :                     warn("%s: root %"PRIx64", not %"PRIx64,
     569                 :            :                          stp_get_name(stp), stp_get_designated_root(stp),
     570                 :            :                          rootid);
     571                 :            :                 }
     572                 :            :             }
     573                 :            : 
     574         [ +  + ]:         84 :             if (match("root")) {
     575         [ -  + ]:         21 :                 if (stp_get_root_path_cost(stp)) {
     576                 :          0 :                     warn("%s: root path cost of root is %u but should be 0",
     577                 :            :                          stp_get_name(stp), stp_get_root_path_cost(stp));
     578                 :            :                 }
     579         [ -  + ]:         21 :                 if (!stp_is_root_bridge(stp)) {
     580                 :          0 :                     warn("%s: root is %"PRIx64", not %"PRIx64,
     581                 :            :                          stp_get_name(stp),
     582                 :            :                          stp_get_designated_root(stp), stp_get_bridge_id(stp));
     583                 :            :                 }
     584         [ +  + ]:         77 :                 for (port_no = 0; port_no < b->n_ports; port_no++) {
     585                 :         56 :                     struct stp_port *p = stp_get_port(stp, port_no);
     586                 :         56 :                     enum stp_state state = stp_port_get_state(p);
     587         [ -  + ]:         56 :                     if (!(state & (STP_DISABLED | STP_FORWARDING))) {
     588                 :          0 :                         warn("%s: root port %d in state %s",
     589                 :          0 :                              stp_get_name(b->stp), port_no,
     590                 :            :                              stp_state_name(state));
     591                 :            :                     }
     592                 :            :                 }
     593                 :            :             } else {
     594         [ +  + ]:      16128 :                 for (port_no = 0; port_no < STP_MAX_PORTS; port_no++) {
     595                 :      16065 :                     struct stp_port *p = stp_get_port(stp, port_no);
     596                 :            :                     enum stp_state state;
     597 [ +  + ][ +  + ]:      16065 :                     if (token == NULL || match("D")) {
     598                 :      15837 :                         state = STP_DISABLED;
     599         [ +  + ]:        228 :                     } else if (match("B")) {
     600                 :         55 :                         state = STP_BLOCKING;
     601         [ +  + ]:        173 :                     } else if (match("Li")) {
     602                 :          8 :                         state = STP_LISTENING;
     603         [ -  + ]:        165 :                     } else if (match("Le")) {
     604                 :          0 :                         state = STP_LEARNING;
     605         [ +  - ]:        165 :                     } else if (match("F")) {
     606                 :        165 :                         state = STP_FORWARDING;
     607         [ #  # ]:          0 :                     } else if (match("_")) {
     608                 :          0 :                         continue;
     609                 :            :                     } else {
     610                 :          0 :                         err("unknown port state %s", token);
     611                 :            :                     }
     612         [ -  + ]:      16065 :                     if (stp_port_get_state(p) != state) {
     613                 :          0 :                         warn("%s port %d: state is %s but should be %s",
     614                 :            :                              stp_get_name(stp), port_no,
     615                 :            :                              stp_state_name(stp_port_get_state(p)),
     616                 :            :                              stp_state_name(state));
     617                 :            :                     }
     618         [ +  + ]:      16065 :                     if (state == STP_FORWARDING) {
     619                 :        165 :                         struct stp_port *root_port = stp_get_root_port(stp);
     620         [ +  + ]:        165 :                         if (match(":")) {
     621                 :         57 :                             int root_path_cost = must_get_int();
     622         [ -  + ]:         57 :                             if (p != root_port) {
     623                 :          0 :                                 warn("%s: port %d is not the root port",
     624                 :            :                                      stp_get_name(stp), port_no);
     625         [ #  # ]:          0 :                                 if (!root_port) {
     626                 :          0 :                                     warn("%s: (there is no root port)",
     627                 :            :                                          stp_get_name(stp));
     628                 :            :                                 } else {
     629                 :          0 :                                     warn("%s: (port %d is the root port)",
     630                 :            :                                          stp_get_name(stp),
     631                 :            :                                          stp_port_no(root_port));
     632                 :            :                                 }
     633         [ -  + ]:         57 :                             } else if (root_path_cost
     634                 :         57 :                                        != stp_get_root_path_cost(stp)) {
     635                 :         57 :                                 warn("%s: root path cost is %u, should be %d",
     636                 :            :                                      stp_get_name(stp),
     637                 :            :                                      stp_get_root_path_cost(stp),
     638                 :            :                                      root_path_cost);
     639                 :            :                             }
     640         [ -  + ]:        108 :                         } else if (p == root_port) {
     641                 :          0 :                             warn("%s: port %d is the root port but "
     642                 :            :                                  "not expected to be",
     643                 :            :                                  stp_get_name(stp), port_no);
     644                 :            :                         }
     645                 :            :                     }
     646                 :            :                 }
     647                 :            :             }
     648         [ -  + ]:         84 :             if (n_warnings) {
     649                 :          0 :                 exit(EXIT_FAILURE);
     650                 :            :             }
     651                 :            :         }
     652         [ -  + ]:        165 :         if (get_token()) {
     653                 :          0 :             err("trailing garbage on line");
     654                 :            :         }
     655                 :            :     }
     656                 :         13 :     free(token);
     657                 :            : 
     658         [ +  + ]:        351 :     for (i = 0; i < tc->n_lans; i++) {
     659                 :        338 :         struct lan *lan = tc->lans[i];
     660                 :        338 :         free(CONST_CAST(char *, lan->name));
     661                 :        338 :         free(lan);
     662                 :            :     }
     663         [ +  + ]:         57 :     for (i = 0; i < tc->n_bridges; i++) {
     664                 :         44 :         struct bridge *bridge = tc->bridges[i];
     665                 :         44 :         stp_unref(bridge->stp);
     666                 :         44 :         free(bridge);
     667                 :            :     }
     668                 :         13 :     free(tc);
     669                 :         13 :     fclose(input_file);
     670                 :         13 : }
     671                 :            : 
     672                 :       1200 : OVSTEST_REGISTER("test-stp", test_stp_main);

Generated by: LCOV version 1.12