LCOV - code coverage report
Current view: top level - ovn/lib - actions.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 913 942 96.9 %
Date: 2016-09-14 01:02:56 Functions: 117 117 100.0 %
Branches: 380 424 89.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 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                 :            : #include <stdarg.h>
      19                 :            : #include <stdbool.h>
      20                 :            : #include "bitmap.h"
      21                 :            : #include "byte-order.h"
      22                 :            : #include "compiler.h"
      23                 :            : #include "ovn-dhcp.h"
      24                 :            : #include "hash.h"
      25                 :            : #include "logical-fields.h"
      26                 :            : #include "nx-match.h"
      27                 :            : #include "openvswitch/dynamic-string.h"
      28                 :            : #include "openvswitch/hmap.h"
      29                 :            : #include "openvswitch/json.h"
      30                 :            : #include "openvswitch/ofp-actions.h"
      31                 :            : #include "openvswitch/ofpbuf.h"
      32                 :            : #include "openvswitch/vlog.h"
      33                 :            : #include "ovn/actions.h"
      34                 :            : #include "ovn/expr.h"
      35                 :            : #include "ovn/lex.h"
      36                 :            : #include "packets.h"
      37                 :            : #include "openvswitch/shash.h"
      38                 :            : #include "simap.h"
      39                 :            : 
      40                 :       1270 : VLOG_DEFINE_THIS_MODULE(actions);
      41                 :            : 
      42                 :            : /* Prototypes for functions to be defined by each action. */
      43                 :            : #define OVNACT(ENUM, STRUCT)                                        \
      44                 :            :     static void format_##ENUM(const struct STRUCT *, struct ds *);  \
      45                 :            :     static void encode_##ENUM(const struct STRUCT *,                \
      46                 :            :                               const struct ovnact_encode_params *,  \
      47                 :            :                               struct ofpbuf *ofpacts);              \
      48                 :            :     static void free_##ENUM(struct STRUCT *a);
      49                 :            : OVNACTS
      50                 :            : #undef OVNACT
      51                 :            : 
      52                 :            : /* Helpers. */
      53                 :            : 
      54                 :            : /* Implementation of ovnact_put_<ENUM>(). */
      55                 :            : void *
      56                 :    1484985 : ovnact_put(struct ofpbuf *ovnacts, enum ovnact_type type, size_t len)
      57                 :            : {
      58                 :            :     struct ovnact *ovnact;
      59                 :            : 
      60                 :    1484985 :     ovnacts->header = ofpbuf_put_uninit(ovnacts, len);
      61                 :    1484985 :     ovnact = ovnacts->header;
      62                 :    1484985 :     ovnact_init(ovnact, type, len);
      63                 :    1484985 :     return ovnact;
      64                 :            : }
      65                 :            : 
      66                 :            : /* Implementation of ovnact_init_<ENUM>(). */
      67                 :            : void
      68                 :    1484985 : ovnact_init(struct ovnact *ovnact, enum ovnact_type type, size_t len)
      69                 :            : {
      70                 :    1484985 :     memset(ovnact, 0, len);
      71                 :    1484985 :     ovnact->type = type;
      72                 :    1484985 :     ovnact->len = len;
      73                 :    1484985 : }
      74                 :            : 
      75                 :            : static size_t
      76                 :      35655 : encode_start_controller_op(enum action_opcode opcode, bool pause,
      77                 :            :                            struct ofpbuf *ofpacts)
      78                 :            : {
      79                 :      35655 :     size_t ofs = ofpacts->size;
      80                 :            : 
      81                 :      35655 :     struct ofpact_controller *oc = ofpact_put_CONTROLLER(ofpacts);
      82                 :      35655 :     oc->max_len = UINT16_MAX;
      83                 :      35655 :     oc->reason = OFPR_ACTION;
      84                 :      35655 :     oc->pause = pause;
      85                 :            : 
      86                 :      35655 :     struct action_header ah = { .opcode = htonl(opcode) };
      87                 :      35655 :     ofpbuf_put(ofpacts, &ah, sizeof ah);
      88                 :            : 
      89                 :      35655 :     return ofs;
      90                 :            : }
      91                 :            : 
      92                 :            : static void
      93                 :      35655 : encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts)
      94                 :            : {
      95                 :      35655 :     struct ofpact_controller *oc = ofpbuf_at_assert(ofpacts, ofs, sizeof *oc);
      96                 :      35655 :     ofpacts->header = oc;
      97                 :      35655 :     oc->userdata_len = ofpacts->size - (ofs + sizeof *oc);
      98                 :      35655 :     ofpact_finish_CONTROLLER(ofpacts, &oc);
      99                 :      35655 : }
     100                 :            : 
     101                 :            : static void
     102                 :      19648 : encode_controller_op(enum action_opcode opcode, struct ofpbuf *ofpacts)
     103                 :            : {
     104                 :      19648 :     size_t ofs = encode_start_controller_op(opcode, false, ofpacts);
     105                 :      19648 :     encode_finish_controller_op(ofs, ofpacts);
     106                 :      19648 : }
     107                 :            : 
     108                 :            : static void
     109                 :     132237 : init_stack(struct ofpact_stack *stack, enum mf_field_id field)
     110                 :            : {
     111                 :     132237 :     stack->subfield.field = mf_from_id(field);
     112                 :     132237 :     stack->subfield.ofs = 0;
     113                 :     132237 :     stack->subfield.n_bits = stack->subfield.field->n_bits;
     114                 :     132237 : }
     115                 :            : 
     116                 :            : struct arg {
     117                 :            :     const struct mf_subfield src;
     118                 :            :     enum mf_field_id dst;
     119                 :            : };
     120                 :            : 
     121                 :            : static void
     122                 :      26819 : encode_setup_args(const struct arg args[], size_t n_args,
     123                 :            :                   struct ofpbuf *ofpacts)
     124                 :            : {
     125                 :            :     /* 1. Save all of the destinations that will be modified. */
     126         [ +  + ]:     100105 :     for (const struct arg *a = args; a < &args[n_args]; a++) {
     127         [ -  + ]:      73286 :         ovs_assert(a->src.n_bits == mf_from_id(a->dst)->n_bits);
     128         [ +  + ]:      73286 :         if (a->src.field->id != a->dst) {
     129                 :      44079 :             init_stack(ofpact_put_STACK_PUSH(ofpacts), a->dst);
     130                 :            :         }
     131                 :            :     }
     132                 :            : 
     133                 :            :     /* 2. Push the sources, in reverse order. */
     134         [ +  + ]:     100105 :     for (size_t i = n_args - 1; i < n_args; i--) {
     135                 :      73286 :         const struct arg *a = &args[i];
     136         [ +  + ]:      73286 :         if (a->src.field->id != a->dst) {
     137                 :      44079 :             ofpact_put_STACK_PUSH(ofpacts)->subfield = a->src;
     138                 :            :         }
     139                 :            :     }
     140                 :            : 
     141                 :            :     /* 3. Pop the sources into the destinations. */
     142         [ +  + ]:     100105 :     for (const struct arg *a = args; a < &args[n_args]; a++) {
     143         [ +  + ]:      73286 :         if (a->src.field->id != a->dst) {
     144                 :      44079 :             init_stack(ofpact_put_STACK_POP(ofpacts), a->dst);
     145                 :            :         }
     146                 :            :     }
     147                 :      26819 : }
     148                 :            : 
     149                 :            : static void
     150                 :      26819 : encode_restore_args(const struct arg args[], size_t n_args,
     151                 :            :                     struct ofpbuf *ofpacts)
     152                 :            : {
     153         [ +  + ]:     100105 :     for (size_t i = n_args - 1; i < n_args; i--) {
     154                 :      73286 :         const struct arg *a = &args[i];
     155         [ +  + ]:      73286 :         if (a->src.field->id != a->dst) {
     156                 :      44079 :             init_stack(ofpact_put_STACK_POP(ofpacts), a->dst);
     157                 :            :         }
     158                 :            :     }
     159                 :      26819 : }
     160                 :            : 
     161                 :            : static void
     162                 :       7171 : put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
     163                 :            :          struct ofpbuf *ofpacts)
     164                 :            : {
     165                 :       7171 :     struct ofpact_set_field *sf = ofpact_put_set_field(ofpacts,
     166                 :            :                                                        mf_from_id(dst), NULL,
     167                 :            :                                                        NULL);
     168                 :       7171 :     ovs_be64 n_value = htonll(value);
     169                 :       7171 :     bitwise_copy(&n_value, 8, 0, sf->value, sf->field->n_bytes, ofs, n_bits);
     170                 :       7171 :     bitwise_one(ofpact_set_field_mask(sf), sf->field->n_bytes, ofs, n_bits);
     171                 :       7171 : }
     172                 :            : 
     173                 :            : /* Context maintained during ovnacts_parse(). */
     174                 :            : struct action_context {
     175                 :            :     const struct ovnact_parse_params *pp; /* Parameters. */
     176                 :            :     struct lexer *lexer;        /* Lexer for pulling more tokens. */
     177                 :            :     struct ofpbuf *ovnacts;     /* Actions. */
     178                 :            :     struct expr *prereqs;       /* Prerequisites to apply to match. */
     179                 :            : };
     180                 :            : 
     181                 :            : static bool parse_action(struct action_context *);
     182                 :            : 
     183                 :            : static bool
     184                 :      73332 : action_parse_field(struct action_context *ctx,
     185                 :            :                    int n_bits, bool rw, struct expr_field *f)
     186                 :            : {
     187         [ +  + ]:      73332 :     if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, f, &ctx->prereqs)) {
     188                 :         14 :         return false;
     189                 :            :     }
     190                 :            : 
     191                 :      73318 :     char *error = expr_type_check(f, n_bits, rw);
     192         [ +  + ]:      73318 :     if (error) {
     193                 :          6 :         lexer_error(ctx->lexer, "%s", error);
     194                 :          6 :         free(error);
     195                 :          6 :         return false;
     196                 :            :     }
     197                 :            : 
     198                 :      73312 :     return true;
     199                 :            : }
     200                 :            : 
     201                 :            : static bool
     202                 :         55 : action_parse_port(struct action_context *ctx, uint16_t *port)
     203                 :            : {
     204         [ +  + ]:         55 :     if (lexer_is_int(ctx->lexer)) {
     205                 :         54 :         int value = ntohll(ctx->lexer->token.value.integer);
     206         [ +  + ]:         54 :         if (value <= UINT16_MAX) {
     207                 :         53 :             *port = value;
     208                 :         53 :             lexer_get(ctx->lexer);
     209                 :         53 :             return true;
     210                 :            :         }
     211                 :            :     }
     212                 :          2 :     lexer_syntax_error(ctx->lexer, "expecting port number");
     213                 :          2 :     return false;
     214                 :            : }
     215                 :            : 
     216                 :            : /* Parses 'prerequisite' as an expression in the context of 'ctx', then adds it
     217                 :            :  * as a conjunction with the existing 'ctx->prereqs'. */
     218                 :            : static void
     219                 :      77931 : add_prerequisite(struct action_context *ctx, const char *prerequisite)
     220                 :            : {
     221                 :            :     struct expr *expr;
     222                 :            :     char *error;
     223                 :            : 
     224                 :      77931 :     expr = expr_parse_string(prerequisite, ctx->pp->symtab, NULL, &error);
     225         [ -  + ]:      77931 :     ovs_assert(!error);
     226                 :      77931 :     ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr);
     227                 :      77931 : }
     228                 :            : 
     229                 :            : static void
     230                 :          6 : format_OUTPUT(const struct ovnact_null *a OVS_UNUSED, struct ds *s)
     231                 :            : {
     232                 :          6 :     ds_put_cstr(s, "output;");
     233                 :          6 : }
     234                 :            : 
     235                 :            : static void
     236                 :     530084 : emit_resubmit(struct ofpbuf *ofpacts, uint8_t ptable)
     237                 :            : {
     238                 :     530084 :     struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ofpacts);
     239                 :     530084 :     resubmit->in_port = OFPP_IN_PORT;
     240                 :     530084 :     resubmit->table_id = ptable;
     241                 :     530084 : }
     242                 :            : 
     243                 :            : static void
     244                 :     188734 : encode_OUTPUT(const struct ovnact_null *a OVS_UNUSED,
     245                 :            :               const struct ovnact_encode_params *ep,
     246                 :            :               struct ofpbuf *ofpacts)
     247                 :            : {
     248                 :     188734 :     emit_resubmit(ofpacts, ep->output_ptable);
     249                 :     188734 : }
     250                 :            : 
     251                 :            : static void
     252                 :     188737 : free_OUTPUT(struct ovnact_null *a OVS_UNUSED)
     253                 :            : {
     254                 :     188737 : }
     255                 :            : 
     256                 :            : static void
     257                 :     334192 : parse_NEXT(struct action_context *ctx)
     258                 :            : {
     259         [ -  + ]:     334192 :     if (!ctx->pp->n_tables) {
     260                 :          0 :         lexer_error(ctx->lexer, "\"next\" action not allowed here.");
     261         [ +  + ]:     334192 :     } else if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
     262                 :            :         int ltable;
     263                 :            : 
     264   [ +  +  +  + ]:         23 :         if (!lexer_force_int(ctx->lexer, &ltable) ||
     265                 :         11 :             !lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
     266                 :          3 :             return;
     267                 :            :         }
     268                 :            : 
     269         [ +  + ]:         10 :         if (ltable >= ctx->pp->n_tables) {
     270                 :          1 :             lexer_error(ctx->lexer,
     271                 :            :                         "\"next\" argument must be in range 0 to %d.",
     272                 :          1 :                          ctx->pp->n_tables - 1);
     273                 :          1 :             return;
     274                 :            :         }
     275                 :            : 
     276                 :          9 :         ovnact_put_NEXT(ctx->ovnacts)->ltable = ltable;
     277                 :            :     } else {
     278         [ +  - ]:     334180 :         if (ctx->pp->cur_ltable < ctx->pp->n_tables) {
     279                 :     334180 :             ovnact_put_NEXT(ctx->ovnacts)->ltable = ctx->pp->cur_ltable + 1;
     280                 :            :         } else {
     281                 :          0 :             lexer_error(ctx->lexer,
     282                 :            :                         "\"next\" action not allowed in last table.");
     283                 :            :         }
     284                 :            :     }
     285                 :            : }
     286                 :            : 
     287                 :            : static void
     288                 :         12 : format_NEXT(const struct ovnact_next *next, struct ds *s)
     289                 :            : {
     290                 :         12 :     ds_put_format(s, "next(%d);", next->ltable);
     291                 :         12 : }
     292                 :            : 
     293                 :            : static void
     294                 :     334179 : encode_NEXT(const struct ovnact_next *next,
     295                 :            :             const struct ovnact_encode_params *ep,
     296                 :            :             struct ofpbuf *ofpacts)
     297                 :            : {
     298                 :     334179 :     emit_resubmit(ofpacts, ep->first_ptable + next->ltable);
     299                 :     334179 : }
     300                 :            : 
     301                 :            : static void
     302                 :     334189 : free_NEXT(struct ovnact_next *a OVS_UNUSED)
     303                 :            : {
     304                 :     334189 : }
     305                 :            : 
     306                 :            : static void
     307                 :     622053 : parse_LOAD(struct action_context *ctx, const struct expr_field *lhs)
     308                 :            : {
     309                 :     622053 :     size_t ofs = ctx->ovnacts->size;
     310                 :     622053 :     struct ovnact_load *load = ovnact_put_LOAD(ctx->ovnacts);
     311                 :     622053 :     load->dst = *lhs;
     312                 :            : 
     313                 :     622053 :     char *error = expr_type_check(lhs, lhs->n_bits, true);
     314         [ +  + ]:     622053 :     if (error) {
     315                 :          1 :         ctx->ovnacts->size = ofs;
     316                 :          1 :         lexer_error(ctx->lexer, "%s", error);
     317                 :          1 :         free(error);
     318                 :          1 :         return;
     319                 :            :     }
     320         [ +  + ]:     622052 :     if (!expr_constant_parse(ctx->lexer, lhs, &load->imm)) {
     321                 :          2 :         ctx->ovnacts->size = ofs;
     322                 :          2 :         return;
     323                 :            :     }
     324                 :            : }
     325                 :            : 
     326                 :            : static enum expr_constant_type
     327                 :     622074 : load_type(const struct ovnact_load *load)
     328                 :            : {
     329                 :     622074 :     return load->dst.symbol->width > 0 ? EXPR_C_INTEGER : EXPR_C_STRING;
     330                 :            : }
     331                 :            : 
     332                 :            : static void
     333                 :         24 : format_LOAD(const struct ovnact_load *load, struct ds *s)
     334                 :            : {
     335                 :         24 :     expr_field_format(&load->dst, s);
     336                 :         24 :     ds_put_cstr(s, " = ");
     337                 :         24 :     expr_constant_format(&load->imm, load_type(load), s);
     338                 :         24 :     ds_put_char(s, ';');
     339                 :         24 : }
     340                 :            : 
     341                 :            : static void
     342                 :     622038 : encode_LOAD(const struct ovnact_load *load,
     343                 :            :             const struct ovnact_encode_params *ep,
     344                 :            :             struct ofpbuf *ofpacts)
     345                 :            : {
     346                 :     622038 :     const union expr_constant *c = &load->imm;
     347                 :     622038 :     struct mf_subfield dst = expr_resolve_field(&load->dst);
     348                 :     622038 :     struct ofpact_set_field *sf = ofpact_put_set_field(ofpacts, dst.field,
     349                 :            :                                                        NULL, NULL);
     350                 :            : 
     351         [ +  + ]:     622038 :     if (load->dst.symbol->width) {
     352                 :     525115 :         bitwise_copy(&c->value, sizeof c->value, 0,
     353                 :    1050230 :                      sf->value, dst.field->n_bytes, dst.ofs,
     354                 :            :                      dst.n_bits);
     355         [ -  + ]:     525115 :         if (c->masked) {
     356                 :          0 :             bitwise_copy(&c->mask, sizeof c->mask, 0,
     357                 :          0 :                          ofpact_set_field_mask(sf), dst.field->n_bytes,
     358                 :            :                          dst.ofs, dst.n_bits);
     359                 :            :         } else {
     360                 :     525115 :             bitwise_one(ofpact_set_field_mask(sf), dst.field->n_bytes,
     361                 :            :                         dst.ofs, dst.n_bits);
     362                 :            :         }
     363                 :            :     } else {
     364                 :            :         uint32_t port;
     365         [ +  + ]:      96923 :         if (!ep->lookup_port(ep->aux, load->imm.string, &port)) {
     366                 :          2 :             port = 0;
     367                 :            :         }
     368                 :      96923 :         bitwise_put(port, sf->value,
     369                 :     193846 :                     sf->field->n_bytes, 0, sf->field->n_bits);
     370                 :      96923 :         bitwise_one(ofpact_set_field_mask(sf), sf->field->n_bytes, 0,
     371                 :      96923 :                     sf->field->n_bits);
     372                 :            :     }
     373                 :     622038 : }
     374                 :            : 
     375                 :            : static void
     376                 :     622050 : free_LOAD(struct ovnact_load *load)
     377                 :            : {
     378                 :     622050 :     expr_constant_destroy(&load->imm, load_type(load));
     379                 :     622050 : }
     380                 :            : 
     381                 :            : static void
     382                 :         22 : format_assignment(const struct ovnact_move *move, const char *operator,
     383                 :            :                   struct ds *s)
     384                 :            : {
     385                 :         22 :     expr_field_format(&move->lhs, s);
     386                 :         22 :     ds_put_format(s, " %s ", operator);
     387                 :         22 :     expr_field_format(&move->rhs, s);
     388                 :         22 :     ds_put_char(s, ';');
     389                 :         22 : }
     390                 :            : 
     391                 :            : static void
     392                 :         12 : format_MOVE(const struct ovnact_move *move, struct ds *s)
     393                 :            : {
     394                 :         12 :     format_assignment(move, "=", s);
     395                 :         12 : }
     396                 :            : 
     397                 :            : static void
     398                 :         10 : format_EXCHANGE(const struct ovnact_move *move, struct ds *s)
     399                 :            : {
     400                 :         10 :     format_assignment(move, "<->", s);
     401                 :         10 : }
     402                 :            : 
     403                 :            : static void
     404                 :     235081 : parse_assignment_action(struct action_context *ctx, bool exchange,
     405                 :            :                         const struct expr_field *lhs)
     406                 :            : {
     407                 :            :     struct expr_field rhs;
     408         [ +  + ]:     235081 :     if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, &rhs, &ctx->prereqs)) {
     409                 :         11 :         return;
     410                 :            :     }
     411                 :            : 
     412                 :     235079 :     const struct expr_symbol *ls = lhs->symbol;
     413                 :     235079 :     const struct expr_symbol *rs = rhs.symbol;
     414         [ +  + ]:     235079 :     if ((ls->width != 0) != (rs->width != 0)) {
     415         [ +  + ]:          2 :         if (exchange) {
     416 [ +  - ][ -  + ]:          1 :             lexer_error(ctx->lexer,
     417                 :            :                         "Can't exchange %s field (%s) with %s field (%s).",
     418                 :          1 :                         ls->width ? "integer" : "string",
     419                 :            :                         ls->name,
     420                 :          1 :                         rs->width ? "integer" : "string",
     421                 :            :                         rs->name);
     422                 :            :         } else {
     423 [ -  + ][ +  - ]:          1 :             lexer_error(ctx->lexer,
     424                 :            :                         "Can't assign %s field (%s) to %s field (%s).",
     425                 :          1 :                         rs->width ? "integer" : "string",
     426                 :            :                         rs->name,
     427                 :          1 :                         ls->width ? "integer" : "string",
     428                 :            :                         ls->name);
     429                 :            :         }
     430                 :          2 :         return;
     431                 :            :     }
     432                 :            : 
     433         [ +  + ]:     235077 :     if (lhs->n_bits != rhs.n_bits) {
     434         [ +  + ]:          2 :         if (exchange) {
     435                 :          1 :             lexer_error(ctx->lexer,
     436                 :            :                         "Can't exchange %d-bit field with %d-bit field.",
     437                 :            :                         lhs->n_bits, rhs.n_bits);
     438                 :            :         } else {
     439                 :          1 :             lexer_error(ctx->lexer,
     440                 :            :                         "Can't assign %d-bit value to %d-bit destination.",
     441                 :            :                         rhs.n_bits, lhs->n_bits);
     442                 :            :         }
     443                 :          2 :         return;
     444 [ +  + ][ +  + ]:     235075 :     } else if (!lhs->n_bits &&
     445                 :      45825 :                ls->field->n_bits != rs->field->n_bits) {
     446         [ +  + ]:          2 :         lexer_error(ctx->lexer, "String fields %s and %s are incompatible for "
     447                 :            :                     "%s.", ls->name, rs->name,
     448                 :            :                     exchange ? "exchange" : "assignment");
     449                 :          2 :         return;
     450                 :            :     }
     451                 :            : 
     452                 :     235073 :     char *error = expr_type_check(lhs, lhs->n_bits, true);
     453         [ +  + ]:     235073 :     if (!error) {
     454                 :     235071 :         error = expr_type_check(&rhs, rhs.n_bits, true);
     455                 :            :     }
     456         [ +  + ]:     235073 :     if (error) {
     457                 :          3 :         lexer_error(ctx->lexer, "%s", error);
     458                 :          3 :         free(error);
     459                 :          3 :         return;
     460                 :            :     }
     461                 :            : 
     462                 :            :     struct ovnact_move *move;
     463                 :     235070 :     move = (exchange
     464                 :      24968 :             ? ovnact_put_EXCHANGE(ctx->ovnacts)
     465         [ +  + ]:     235070 :             : ovnact_put_MOVE(ctx->ovnacts));
     466                 :     235070 :     move->lhs = *lhs;
     467                 :     235070 :     move->rhs = rhs;
     468                 :            : }
     469                 :            : 
     470                 :            : static void
     471                 :     210096 : encode_MOVE(const struct ovnact_move *move,
     472                 :            :             const struct ovnact_encode_params *ep OVS_UNUSED,
     473                 :            :             struct ofpbuf *ofpacts)
     474                 :            : {
     475                 :     210096 :     struct ofpact_reg_move *orm = ofpact_put_REG_MOVE(ofpacts);
     476                 :     210096 :     orm->src = expr_resolve_field(&move->rhs);
     477                 :     210096 :     orm->dst = expr_resolve_field(&move->lhs);
     478                 :     210096 : }
     479                 :            : 
     480                 :            : static void
     481                 :      24963 : encode_EXCHANGE(const struct ovnact_move *xchg,
     482                 :            :                 const struct ovnact_encode_params *ep OVS_UNUSED,
     483                 :            :                 struct ofpbuf *ofpacts)
     484                 :            : {
     485                 :      24963 :     ofpact_put_STACK_PUSH(ofpacts)->subfield = expr_resolve_field(&xchg->rhs);
     486                 :      24963 :     ofpact_put_STACK_PUSH(ofpacts)->subfield = expr_resolve_field(&xchg->lhs);
     487                 :      24963 :     ofpact_put_STACK_POP(ofpacts)->subfield = expr_resolve_field(&xchg->rhs);
     488                 :      24963 :     ofpact_put_STACK_POP(ofpacts)->subfield = expr_resolve_field(&xchg->lhs);
     489                 :      24963 : }
     490                 :            : 
     491                 :            : static void
     492                 :     210102 : free_MOVE(struct ovnact_move *move OVS_UNUSED)
     493                 :            : {
     494                 :     210102 : }
     495                 :            : 
     496                 :            : static void
     497                 :      24968 : free_EXCHANGE(struct ovnact_move *xchg OVS_UNUSED)
     498                 :            : {
     499                 :      24968 : }
     500                 :            : 
     501                 :            : static void
     502                 :      25814 : parse_DEC_TTL(struct action_context *ctx)
     503                 :            : {
     504                 :      25814 :     lexer_force_match(ctx->lexer, LEX_T_DECREMENT);
     505                 :      25814 :     ovnact_put_DEC_TTL(ctx->ovnacts);
     506                 :      25814 :     add_prerequisite(ctx, "ip");
     507                 :      25814 : }
     508                 :            : 
     509                 :            : static void
     510                 :          2 : format_DEC_TTL(const struct ovnact_null *null OVS_UNUSED, struct ds *s)
     511                 :            : {
     512                 :          2 :     ds_put_cstr(s, "ip.ttl--;");
     513                 :          2 : }
     514                 :            : 
     515                 :            : static void
     516                 :      25812 : encode_DEC_TTL(const struct ovnact_null *null OVS_UNUSED,
     517                 :            :                const struct ovnact_encode_params *ep OVS_UNUSED,
     518                 :            :                struct ofpbuf *ofpacts)
     519                 :            : {
     520                 :      25812 :     ofpact_put_DEC_TTL(ofpacts);
     521                 :      25812 : }
     522                 :            : 
     523                 :            : static void
     524                 :      25814 : free_DEC_TTL(struct ovnact_null *null OVS_UNUSED)
     525                 :            : {
     526                 :      25814 : }
     527                 :            : 
     528                 :            : static void
     529                 :      11931 : parse_CT_NEXT(struct action_context *ctx)
     530                 :            : {
     531         [ -  + ]:      11931 :     if (ctx->pp->cur_ltable >= ctx->pp->n_tables) {
     532                 :          0 :         lexer_error(ctx->lexer,
     533                 :            :                     "\"ct_next\" action not allowed in last table.");
     534                 :          0 :         return;
     535                 :            :     }
     536                 :            : 
     537                 :      11931 :     add_prerequisite(ctx, "ip");
     538                 :      11931 :     ovnact_put_CT_NEXT(ctx->ovnacts)->ltable = ctx->pp->cur_ltable + 1;
     539                 :            : }
     540                 :            : 
     541                 :            : static void
     542                 :          2 : format_CT_NEXT(const struct ovnact_next *next OVS_UNUSED, struct ds *s)
     543                 :            : {
     544                 :          2 :     ds_put_cstr(s, "ct_next;");
     545                 :          2 : }
     546                 :            : 
     547                 :            : static void
     548                 :      11930 : encode_CT_NEXT(const struct ovnact_next *next,
     549                 :            :                 const struct ovnact_encode_params *ep,
     550                 :            :                 struct ofpbuf *ofpacts)
     551                 :            : {
     552                 :      11930 :     struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
     553                 :      11930 :     ct->recirc_table = ep->first_ptable + next->ltable;
     554                 :      11930 :     ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
     555                 :      11930 :     ct->zone_src.ofs = 0;
     556                 :      11930 :     ct->zone_src.n_bits = 16;
     557                 :      11930 :     ofpact_finish(ofpacts, &ct->ofpact);
     558                 :      11930 : }
     559                 :            : 
     560                 :            : static void
     561                 :      11931 : free_CT_NEXT(struct ovnact_next *next OVS_UNUSED)
     562                 :            : {
     563                 :      11931 : }
     564                 :            : 
     565                 :            : static void
     566                 :      11927 : parse_ct_commit_arg(struct action_context *ctx,
     567                 :            :                     struct ovnact_ct_commit *cc)
     568                 :            : {
     569         [ +  + ]:      11927 :     if (lexer_match_id(ctx->lexer, "ct_mark")) {
     570         [ -  + ]:          6 :         if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
     571                 :          0 :             return;
     572                 :            :         }
     573         [ +  + ]:          6 :         if (ctx->lexer->token.type == LEX_T_INTEGER) {
     574                 :          4 :             cc->ct_mark = ntohll(ctx->lexer->token.value.integer);
     575                 :          4 :             cc->ct_mark_mask = UINT32_MAX;
     576         [ +  - ]:          2 :         } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
     577                 :          2 :             cc->ct_mark = ntohll(ctx->lexer->token.value.integer);
     578                 :          2 :             cc->ct_mark_mask = ntohll(ctx->lexer->token.mask.integer);
     579                 :            :         } else {
     580                 :          0 :             lexer_syntax_error(ctx->lexer, "expecting integer");
     581                 :          0 :             return;
     582                 :            :         }
     583                 :          6 :         lexer_get(ctx->lexer);
     584         [ +  - ]:      11921 :     } else if (lexer_match_id(ctx->lexer, "ct_label")) {
     585         [ -  + ]:      11921 :         if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
     586                 :          0 :             return;
     587                 :            :         }
     588         [ +  + ]:      11921 :         if (ctx->lexer->token.type == LEX_T_INTEGER) {
     589                 :         10 :             cc->ct_label = ctx->lexer->token.value.be128_int;
     590                 :         10 :             cc->ct_label_mask = OVS_BE128_MAX;
     591         [ +  + ]:      11911 :         } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
     592                 :      11910 :             cc->ct_label = ctx->lexer->token.value.be128_int;
     593                 :      11910 :             cc->ct_label_mask = ctx->lexer->token.mask.be128_int;
     594                 :            :         } else {
     595                 :          1 :             lexer_syntax_error(ctx->lexer, "expecting integer");
     596                 :          1 :             return;
     597                 :            :         }
     598                 :      11920 :         lexer_get(ctx->lexer);
     599                 :            :     } else {
     600                 :          0 :         lexer_syntax_error(ctx->lexer, NULL);
     601                 :            :     }
     602                 :            : }
     603                 :            : 
     604                 :            : static void
     605                 :      11929 : parse_CT_COMMIT(struct action_context *ctx)
     606                 :            : {
     607                 :      11929 :     add_prerequisite(ctx, "ip");
     608                 :            : 
     609                 :      11929 :     struct ovnact_ct_commit *ct_commit = ovnact_put_CT_COMMIT(ctx->ovnacts);
     610         [ +  + ]:      11929 :     if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
     611         [ +  + ]:      23852 :         while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
     612                 :      11927 :             parse_ct_commit_arg(ctx, ct_commit);
     613         [ +  + ]:      11927 :             if (ctx->lexer->error) {
     614                 :          1 :                 return;
     615                 :            :             }
     616                 :      11926 :             lexer_match(ctx->lexer, LEX_T_COMMA);
     617                 :            :         }
     618                 :            :     }
     619                 :            : }
     620                 :            : 
     621                 :            : static void
     622                 :         22 : format_CT_COMMIT(const struct ovnact_ct_commit *cc, struct ds *s)
     623                 :            : {
     624                 :         22 :     ds_put_cstr(s, "ct_commit(");
     625         [ +  + ]:         22 :     if (cc->ct_mark_mask) {
     626                 :          6 :         ds_put_format(s, "ct_mark=%#"PRIx32, cc->ct_mark);
     627         [ +  + ]:          6 :         if (cc->ct_mark_mask != UINT32_MAX) {
     628                 :          2 :             ds_put_format(s, "/%#"PRIx32, cc->ct_mark_mask);
     629                 :            :         }
     630                 :            :     }
     631         [ +  + ]:         22 :     if (!ovs_be128_is_zero(cc->ct_label_mask)) {
     632         [ +  + ]:         14 :         if (ds_last(s) != '(') {
     633                 :          2 :             ds_put_cstr(s, ", ");
     634                 :            :         }
     635                 :            : 
     636                 :         14 :         ds_put_format(s, "ct_label=");
     637                 :         14 :         ds_put_hex(s, &cc->ct_label, sizeof cc->ct_label);
     638         [ +  + ]:         14 :         if (!ovs_be128_equals(cc->ct_label_mask, OVS_BE128_MAX)) {
     639                 :          4 :             ds_put_char(s, '/');
     640                 :          4 :             ds_put_hex(s, &cc->ct_label_mask, sizeof cc->ct_label_mask);
     641                 :            :         }
     642                 :            :     }
     643         [ +  + ]:         22 :     if (!ds_chomp(s, '(')) {
     644                 :         18 :         ds_put_char(s, ')');
     645                 :            :     }
     646                 :         22 :     ds_put_char(s, ';');
     647                 :         22 : }
     648                 :            : 
     649                 :            : static void
     650                 :      11917 : encode_CT_COMMIT(const struct ovnact_ct_commit *cc,
     651                 :            :                  const struct ovnact_encode_params *ep OVS_UNUSED,
     652                 :            :                  struct ofpbuf *ofpacts)
     653                 :            : {
     654                 :      11917 :     struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
     655                 :      11917 :     ct->flags = NX_CT_F_COMMIT;
     656                 :      11917 :     ct->recirc_table = NX_CT_RECIRC_NONE;
     657                 :      11917 :     ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
     658                 :      11917 :     ct->zone_src.ofs = 0;
     659                 :      11917 :     ct->zone_src.n_bits = 16;
     660                 :            : 
     661                 :      11917 :     size_t set_field_offset = ofpacts->size;
     662                 :      11917 :     ofpbuf_pull(ofpacts, set_field_offset);
     663                 :            : 
     664         [ +  + ]:      11917 :     if (cc->ct_mark_mask) {
     665                 :          3 :         const ovs_be32 value = htonl(cc->ct_mark);
     666                 :          3 :         const ovs_be32 mask = htonl(cc->ct_mark_mask);
     667                 :          3 :         ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_MARK), &value, &mask);
     668                 :            :     }
     669                 :            : 
     670         [ +  + ]:      11917 :     if (!ovs_be128_is_zero(cc->ct_label_mask)) {
     671                 :      11913 :         ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_LABEL), &cc->ct_label,
     672                 :      11913 :                              &cc->ct_label_mask);
     673                 :            :     }
     674                 :            : 
     675                 :      11917 :     ofpacts->header = ofpbuf_push_uninit(ofpacts, set_field_offset);
     676                 :      11917 :     ct = ofpacts->header;
     677                 :      11917 :     ofpact_finish(ofpacts, &ct->ofpact);
     678                 :      11917 : }
     679                 :            : 
     680                 :            : static void
     681                 :      11929 : free_CT_COMMIT(struct ovnact_ct_commit *cc OVS_UNUSED)
     682                 :            : {
     683                 :      11929 : }
     684                 :            : 
     685                 :            : static void
     686                 :        425 : parse_ct_nat(struct action_context *ctx, const char *name,
     687                 :            :              struct ovnact_ct_nat *cn)
     688                 :            : {
     689                 :        425 :     add_prerequisite(ctx, "ip");
     690                 :            : 
     691         [ -  + ]:        425 :     if (ctx->pp->cur_ltable >= ctx->pp->n_tables) {
     692                 :          0 :         lexer_error(ctx->lexer,
     693                 :            :                     "\"%s\" action not allowed in last table.", name);
     694                 :          0 :         return;
     695                 :            :     }
     696                 :        425 :     cn->ltable = ctx->pp->cur_ltable + 1;
     697                 :            : 
     698         [ +  + ]:        425 :     if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
     699         [ +  + ]:         50 :         if (ctx->lexer->token.type != LEX_T_INTEGER
     700         [ -  + ]:         44 :             || ctx->lexer->token.format != LEX_F_IPV4) {
     701                 :          6 :             lexer_syntax_error(ctx->lexer, "expecting IPv4 address");
     702                 :          6 :             return;
     703                 :            :         }
     704                 :         44 :         cn->ip = ctx->lexer->token.value.ipv4;
     705                 :         44 :         lexer_get(ctx->lexer);
     706                 :            : 
     707         [ +  + ]:         44 :         if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
     708                 :          2 :             return;
     709                 :            :         }
     710                 :            :     }
     711                 :            : }
     712                 :            : 
     713                 :            : static void
     714                 :        371 : parse_CT_DNAT(struct action_context *ctx)
     715                 :            : {
     716                 :        371 :     parse_ct_nat(ctx, "ct_dnat", ovnact_put_CT_DNAT(ctx->ovnacts));
     717                 :        371 : }
     718                 :            : 
     719                 :            : static void
     720                 :         54 : parse_CT_SNAT(struct action_context *ctx)
     721                 :            : {
     722                 :         54 :     parse_ct_nat(ctx, "ct_snat", ovnact_put_CT_SNAT(ctx->ovnacts));
     723                 :         54 : }
     724                 :            : 
     725                 :            : static void
     726                 :          8 : format_ct_nat(const struct ovnact_ct_nat *cn, const char *name, struct ds *s)
     727                 :            : {
     728                 :          8 :     ds_put_cstr(s, name);
     729         [ +  + ]:          8 :     if (cn->ip) {
     730                 :          4 :         ds_put_format(s, "("IP_FMT")", IP_ARGS(cn->ip));
     731                 :            :     }
     732                 :          8 :     ds_put_char(s, ';');
     733                 :          8 : }
     734                 :            : 
     735                 :            : static void
     736                 :          4 : format_CT_DNAT(const struct ovnact_ct_nat *cn, struct ds *s)
     737                 :            : {
     738                 :          4 :     format_ct_nat(cn, "ct_dnat", s);
     739                 :          4 : }
     740                 :            : 
     741                 :            : static void
     742                 :          4 : format_CT_SNAT(const struct ovnact_ct_nat *cn, struct ds *s)
     743                 :            : {
     744                 :          4 :     format_ct_nat(cn, "ct_snat", s);
     745                 :          4 : }
     746                 :            : 
     747                 :            : static void
     748                 :        413 : encode_ct_nat(const struct ovnact_ct_nat *cn,
     749                 :            :               const struct ovnact_encode_params *ep,
     750                 :            :               bool snat, struct ofpbuf *ofpacts)
     751                 :            : {
     752                 :        413 :     const size_t ct_offset = ofpacts->size;
     753                 :        413 :     ofpbuf_pull(ofpacts, ct_offset);
     754                 :            : 
     755                 :        413 :     struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
     756                 :        413 :     ct->recirc_table = cn->ltable + ep->first_ptable;
     757         [ +  + ]:        413 :     if (snat) {
     758                 :         48 :         ct->zone_src.field = mf_from_id(MFF_LOG_SNAT_ZONE);
     759                 :            :     } else {
     760                 :        365 :         ct->zone_src.field = mf_from_id(MFF_LOG_DNAT_ZONE);
     761                 :            :     }
     762                 :        413 :     ct->zone_src.ofs = 0;
     763                 :        413 :     ct->zone_src.n_bits = 16;
     764                 :        413 :     ct->flags = 0;
     765                 :        413 :     ct->alg = 0;
     766                 :            : 
     767                 :            :     struct ofpact_nat *nat;
     768                 :            :     size_t nat_offset;
     769                 :        413 :     nat_offset = ofpacts->size;
     770                 :        413 :     ofpbuf_pull(ofpacts, nat_offset);
     771                 :            : 
     772                 :        413 :     nat = ofpact_put_NAT(ofpacts);
     773                 :        413 :     nat->flags = 0;
     774                 :        413 :     nat->range_af = AF_UNSPEC;
     775                 :            : 
     776         [ +  + ]:        413 :     if (cn->ip) {
     777                 :         40 :         nat->range_af = AF_INET;
     778                 :         40 :         nat->range.addr.ipv4.min = cn->ip;
     779         [ +  + ]:         40 :         if (snat) {
     780                 :         24 :             nat->flags |= NX_NAT_F_SRC;
     781                 :            :         } else {
     782                 :         16 :             nat->flags |= NX_NAT_F_DST;
     783                 :            :         }
     784                 :            :     }
     785                 :            : 
     786                 :        413 :     ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset);
     787                 :        413 :     ct = ofpacts->header;
     788         [ +  + ]:        413 :     if (cn->ip) {
     789                 :         40 :         ct->flags |= NX_CT_F_COMMIT;
     790         [ +  + ]:        373 :     } else if (snat) {
     791                 :            :         /* XXX: For performance reasons, we try to prevent additional
     792                 :            :          * recirculations.  So far, ct_snat which is used in a gateway router
     793                 :            :          * does not need a recirculation. ct_snat(IP) does need a
     794                 :            :          * recirculation.  Should we consider a method to let the actions
     795                 :            :          * specify whether an action needs recirculation if there more use
     796                 :            :          * cases?. */
     797                 :         24 :         ct->recirc_table = NX_CT_RECIRC_NONE;
     798                 :            :     }
     799                 :        413 :     ofpact_finish(ofpacts, &ct->ofpact);
     800                 :        413 :     ofpbuf_push_uninit(ofpacts, ct_offset);
     801                 :        413 : }
     802                 :            : 
     803                 :            : static void
     804                 :        365 : encode_CT_DNAT(const struct ovnact_ct_nat *cn,
     805                 :            :                const struct ovnact_encode_params *ep,
     806                 :            :                struct ofpbuf *ofpacts)
     807                 :            : {
     808                 :        365 :     encode_ct_nat(cn, ep, false, ofpacts);
     809                 :        365 : }
     810                 :            : 
     811                 :            : static void
     812                 :         48 : encode_CT_SNAT(const struct ovnact_ct_nat *cn,
     813                 :            :                const struct ovnact_encode_params *ep,
     814                 :            :                struct ofpbuf *ofpacts)
     815                 :            : {
     816                 :         48 :     encode_ct_nat(cn, ep, true, ofpacts);
     817                 :         48 : }
     818                 :            : 
     819                 :            : static void
     820                 :        371 : free_CT_DNAT(struct ovnact_ct_nat *ct_nat OVS_UNUSED)
     821                 :            : {
     822                 :        371 : }
     823                 :            : 
     824                 :            : static void
     825                 :         54 : free_CT_SNAT(struct ovnact_ct_nat *ct_nat OVS_UNUSED)
     826                 :            : {
     827                 :         54 : }
     828                 :            : 
     829                 :            : static void
     830                 :      11970 : parse_ct_lb_action(struct action_context *ctx)
     831                 :            : {
     832         [ -  + ]:      11970 :     if (ctx->pp->cur_ltable >= ctx->pp->n_tables) {
     833                 :          0 :         lexer_error(ctx->lexer, "\"ct_lb\" action not allowed in last table.");
     834                 :          3 :         return;
     835                 :            :     }
     836                 :            : 
     837                 :      11970 :     add_prerequisite(ctx, "ip");
     838                 :            : 
     839                 :      11970 :     struct ovnact_ct_lb_dst *dsts = NULL;
     840                 :      11970 :     size_t allocated_dsts = 0;
     841                 :      11970 :     size_t n_dsts = 0;
     842                 :            : 
     843         [ +  + ]:      11970 :     if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
     844         [ +  + ]:        205 :         while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
     845         [ +  + ]:        147 :             if (ctx->lexer->token.type != LEX_T_INTEGER
     846         [ -  + ]:        146 :                 || mf_subvalue_width(&ctx->lexer->token.value) > 32) {
     847                 :          1 :                 lexer_syntax_error(ctx->lexer, "expecting IPv4 address");
     848                 :          3 :                 return;
     849                 :            :             }
     850                 :            : 
     851                 :            :             /* Parse IP. */
     852                 :        146 :             ovs_be32 ip = ctx->lexer->token.value.ipv4;
     853                 :        146 :             lexer_get(ctx->lexer);
     854                 :            : 
     855                 :            :             /* Parse optional port. */
     856                 :        146 :             uint16_t port = 0;
     857         [ +  + ]:        146 :             if (lexer_match(ctx->lexer, LEX_T_COLON)
     858         [ +  + ]:         55 :                 && !action_parse_port(ctx, &port)) {
     859                 :          2 :                 free(dsts);
     860                 :          2 :                 return;
     861                 :            :             }
     862                 :        144 :             lexer_match(ctx->lexer, LEX_T_COMMA);
     863                 :            : 
     864                 :            :             /* Append to dsts. */
     865         [ +  - ]:        144 :             if (n_dsts >= allocated_dsts) {
     866                 :        144 :                 dsts = x2nrealloc(dsts, &allocated_dsts, sizeof *dsts);
     867                 :            :             }
     868                 :        144 :             dsts[n_dsts++] = (struct ovnact_ct_lb_dst) { ip, port };
     869                 :            :         }
     870                 :            :     }
     871                 :            : 
     872                 :      11967 :     struct ovnact_ct_lb *cl = ovnact_put_CT_LB(ctx->ovnacts);
     873                 :      11967 :     cl->ltable = ctx->pp->cur_ltable + 1;
     874                 :      11967 :     cl->dsts = dsts;
     875                 :      11967 :     cl->n_dsts = n_dsts;
     876                 :            : }
     877                 :            : 
     878                 :            : static void
     879                 :          8 : format_CT_LB(const struct ovnact_ct_lb *cl, struct ds *s)
     880                 :            : {
     881                 :          8 :     ds_put_cstr(s, "ct_lb");
     882         [ +  + ]:          8 :     if (cl->n_dsts) {
     883                 :          4 :         ds_put_char(s, '(');
     884         [ +  + ]:         12 :         for (size_t i = 0; i < cl->n_dsts; i++) {
     885         [ +  + ]:          8 :             if (i) {
     886                 :          4 :                 ds_put_cstr(s, ", ");
     887                 :            :             }
     888                 :            : 
     889                 :          8 :             const struct ovnact_ct_lb_dst *dst = &cl->dsts[i];
     890                 :          8 :             ds_put_format(s, IP_FMT, IP_ARGS(dst->ip));
     891         [ +  + ]:          8 :             if (dst->port) {
     892                 :          4 :                 ds_put_format(s, ":%"PRIu16, dst->port);
     893                 :            :             }
     894                 :            :         }
     895                 :          4 :         ds_put_char(s, ')');
     896                 :            :     }
     897                 :          8 :     ds_put_char(s, ';');
     898                 :          8 : }
     899                 :            : 
     900                 :            : static void
     901                 :      11963 : encode_CT_LB(const struct ovnact_ct_lb *cl,
     902                 :            :              const struct ovnact_encode_params *ep,
     903                 :            :              struct ofpbuf *ofpacts)
     904                 :            : {
     905                 :      11963 :     uint8_t recirc_table = cl->ltable + ep->first_ptable;
     906         [ +  + ]:      11963 :     if (!cl->n_dsts) {
     907                 :            :         /* ct_lb without any destinations means that this is an established
     908                 :            :          * connection and we just need to do a NAT. */
     909                 :      11908 :         const size_t ct_offset = ofpacts->size;
     910                 :      11908 :         ofpbuf_pull(ofpacts, ct_offset);
     911                 :            : 
     912                 :      11908 :         struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
     913                 :            :         struct ofpact_nat *nat;
     914                 :            :         size_t nat_offset;
     915                 :      23816 :         ct->zone_src.field = ep->is_switch ? mf_from_id(MFF_LOG_CT_ZONE)
     916         [ +  - ]:      11908 :                                 : mf_from_id(MFF_LOG_DNAT_ZONE);
     917                 :      11908 :         ct->zone_src.ofs = 0;
     918                 :      11908 :         ct->zone_src.n_bits = 16;
     919                 :      11908 :         ct->flags = 0;
     920                 :      11908 :         ct->recirc_table = recirc_table;
     921                 :      11908 :         ct->alg = 0;
     922                 :            : 
     923                 :      11908 :         nat_offset = ofpacts->size;
     924                 :      11908 :         ofpbuf_pull(ofpacts, nat_offset);
     925                 :            : 
     926                 :      11908 :         nat = ofpact_put_NAT(ofpacts);
     927                 :      11908 :         nat->flags = 0;
     928                 :      11908 :         nat->range_af = AF_UNSPEC;
     929                 :            : 
     930                 :      11908 :         ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset);
     931                 :      11908 :         ct = ofpacts->header;
     932                 :      11908 :         ofpact_finish(ofpacts, &ct->ofpact);
     933                 :      11908 :         ofpbuf_push_uninit(ofpacts, ct_offset);
     934                 :      11908 :         return;
     935                 :            :     }
     936                 :            : 
     937                 :         55 :     uint32_t group_id = 0, hash;
     938                 :            :     struct group_info *group_info;
     939                 :            :     struct ofpact_group *og;
     940         [ +  + ]:         55 :     uint32_t zone_reg = ep->is_switch ? MFF_LOG_CT_ZONE - MFF_REG0
     941                 :            :                             : MFF_LOG_DNAT_ZONE - MFF_REG0;
     942                 :            : 
     943                 :         55 :     struct ds ds = DS_EMPTY_INITIALIZER;
     944                 :         55 :     ds_put_format(&ds, "type=select");
     945                 :            : 
     946                 :            :     BUILD_ASSERT(MFF_LOG_CT_ZONE >= MFF_REG0);
     947                 :            :     BUILD_ASSERT(MFF_LOG_CT_ZONE < MFF_REG0 + FLOW_N_REGS);
     948                 :            :     BUILD_ASSERT(MFF_LOG_DNAT_ZONE >= MFF_REG0);
     949                 :            :     BUILD_ASSERT(MFF_LOG_DNAT_ZONE < MFF_REG0 + FLOW_N_REGS);
     950         [ +  + ]:        195 :     for (size_t bucket_id = 0; bucket_id < cl->n_dsts; bucket_id++) {
     951                 :        140 :         const struct ovnact_ct_lb_dst *dst = &cl->dsts[bucket_id];
     952                 :        140 :         ds_put_format(&ds, ",bucket=bucket_id=%"PRIuSIZE",weight:100,actions="
     953                 :        140 :                       "ct(nat(dst="IP_FMT, bucket_id, IP_ARGS(dst->ip));
     954         [ +  + ]:        140 :         if (dst->port) {
     955                 :         51 :             ds_put_format(&ds, ":%"PRIu16, dst->port);
     956                 :            :         }
     957                 :        140 :         ds_put_format(&ds, "),commit,table=%d,zone=NXM_NX_REG%d[0..15])",
     958                 :            :                       recirc_table, zone_reg);
     959                 :            :     }
     960                 :            : 
     961                 :         55 :     hash = hash_string(ds_cstr(&ds), 0);
     962                 :            : 
     963                 :            :     /* Check whether we have non installed but allocated group_id. */
     964 [ +  + ][ -  + ]:         55 :     HMAP_FOR_EACH_WITH_HASH (group_info, hmap_node, hash,
     965                 :            :                              &ep->group_table->desired_groups) {
     966         [ +  - ]:          6 :         if (!strcmp(ds_cstr(&group_info->group), ds_cstr(&ds))) {
     967                 :          6 :             group_id = group_info->group_id;
     968                 :          6 :             break;
     969                 :            :         }
     970                 :            :     }
     971                 :            : 
     972         [ +  + ]:         55 :     if (!group_id) {
     973                 :            :         /* Check whether we already have an installed entry for this
     974                 :            :          * combination. */
     975 [ +  + ][ -  + ]:         90 :         HMAP_FOR_EACH_WITH_HASH (group_info, hmap_node, hash,
     976                 :            :                                  &ep->group_table->existing_groups) {
     977         [ +  - ]:         41 :             if (!strcmp(ds_cstr(&group_info->group), ds_cstr(&ds))) {
     978                 :         41 :                 group_id = group_info->group_id;
     979                 :            :             }
     980                 :            :         }
     981                 :            : 
     982                 :         49 :         bool new_group_id = false;
     983         [ +  + ]:         49 :         if (!group_id) {
     984                 :            :             /* Reserve a new group_id. */
     985                 :          8 :             group_id = bitmap_scan(ep->group_table->group_ids, 0, 1,
     986                 :            :                                    MAX_OVN_GROUPS + 1);
     987                 :          8 :             new_group_id = true;
     988                 :            :         }
     989                 :            : 
     990         [ -  + ]:         49 :         if (group_id == MAX_OVN_GROUPS + 1) {
     991                 :            :             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
     992         [ #  # ]:          0 :             VLOG_ERR_RL(&rl, "out of group ids");
     993                 :            : 
     994                 :          0 :             ds_destroy(&ds);
     995                 :          0 :             return;
     996                 :            :         }
     997                 :         49 :         bitmap_set1(ep->group_table->group_ids, group_id);
     998                 :            : 
     999                 :         49 :         group_info = xmalloc(sizeof *group_info);
    1000                 :         49 :         group_info->group = ds;
    1001                 :         49 :         group_info->group_id = group_id;
    1002                 :         49 :         group_info->hmap_node.hash = hash;
    1003                 :         49 :         group_info->new_group_id = new_group_id;
    1004                 :            : 
    1005                 :         49 :         hmap_insert(&ep->group_table->desired_groups,
    1006                 :            :                     &group_info->hmap_node, group_info->hmap_node.hash);
    1007                 :            :     } else {
    1008                 :          6 :         ds_destroy(&ds);
    1009                 :            :     }
    1010                 :            : 
    1011                 :            :     /* Create an action to set the group. */
    1012                 :         55 :     og = ofpact_put_GROUP(ofpacts);
    1013                 :         55 :     og->group_id = group_id;
    1014                 :            : }
    1015                 :            : 
    1016                 :            : static void
    1017                 :      11967 : free_CT_LB(struct ovnact_ct_lb *ct_lb)
    1018                 :            : {
    1019                 :      11967 :     free(ct_lb->dsts);
    1020                 :      11967 : }
    1021                 :            : 
    1022                 :            : /* Implements the "arp" and "nd_na" actions, which execute nested actions on a
    1023                 :            :  * packet derived from the one being processed. */
    1024                 :            : static void
    1025                 :      15862 : parse_nested_action(struct action_context *ctx, enum ovnact_type type,
    1026                 :            :                     const char *prereq)
    1027                 :            : {
    1028         [ -  + ]:      15862 :     if (!lexer_force_match(ctx->lexer, LEX_T_LCURLY)) {
    1029                 :          0 :         return;
    1030                 :            :     }
    1031                 :            : 
    1032                 :            :     uint64_t stub[1024 / 8];
    1033                 :      15862 :     struct ofpbuf nested = OFPBUF_STUB_INITIALIZER(stub);
    1034                 :            : 
    1035                 :      31724 :     struct action_context inner_ctx = {
    1036                 :      15862 :         .pp = ctx->pp,
    1037                 :      15862 :         .lexer = ctx->lexer,
    1038                 :            :         .ovnacts = &nested,
    1039                 :            :         .prereqs = NULL
    1040                 :            :     };
    1041         [ +  + ]:     122104 :     while (!lexer_match(ctx->lexer, LEX_T_RCURLY)) {
    1042         [ -  + ]:     106242 :         if (!parse_action(&inner_ctx)) {
    1043                 :          0 :             break;
    1044                 :            :         }
    1045                 :            :     }
    1046                 :            : 
    1047                 :            :     /* XXX Not really sure what we should do with prerequisites for nested
    1048                 :            :      * actions. */
    1049                 :      15862 :     expr_destroy(inner_ctx.prereqs);
    1050                 :            : 
    1051         [ -  + ]:      15862 :     if (inner_ctx.lexer->error) {
    1052                 :          0 :         ovnacts_free(nested.data, nested.size);
    1053                 :          0 :         ofpbuf_uninit(&nested);
    1054                 :          0 :         return;
    1055                 :            :     }
    1056                 :            : 
    1057                 :      15862 :     add_prerequisite(ctx, prereq);
    1058                 :            : 
    1059                 :      15862 :     struct ovnact_nest *on = ovnact_put(ctx->ovnacts, type, sizeof *on);
    1060                 :      15862 :     on->nested_len = nested.size;
    1061                 :      15862 :     on->nested = ofpbuf_steal_data(&nested);
    1062                 :            : }
    1063                 :            : 
    1064                 :            : static void
    1065                 :       2391 : parse_ARP(struct action_context *ctx)
    1066                 :            : {
    1067                 :       2391 :     parse_nested_action(ctx, OVNACT_ARP, "ip4");
    1068                 :       2391 : }
    1069                 :            : 
    1070                 :            : static void
    1071                 :      13471 : parse_ND_NA(struct action_context *ctx)
    1072                 :            : {
    1073                 :      13471 :     parse_nested_action(ctx, OVNACT_ND_NA, "nd_ns");
    1074                 :      13471 : }
    1075                 :            : 
    1076                 :            : static void
    1077                 :          4 : format_nested_action(const struct ovnact_nest *on, const char *name,
    1078                 :            :                      struct ds *s)
    1079                 :            : {
    1080                 :          4 :     ds_put_format(s, "%s { ", name);
    1081                 :          4 :     ovnacts_format(on->nested, on->nested_len, s);
    1082                 :          4 :     ds_put_format(s, " };");
    1083                 :          4 : }
    1084                 :            : 
    1085                 :            : static void
    1086                 :          2 : format_ARP(const struct ovnact_nest *nest, struct ds *s)
    1087                 :            : {
    1088                 :          2 :     format_nested_action(nest, "arp", s);
    1089                 :          2 : }
    1090                 :            : 
    1091                 :            : static void
    1092                 :          2 : format_ND_NA(const struct ovnact_nest *nest, struct ds *s)
    1093                 :            : {
    1094                 :          2 :     format_nested_action(nest, "nd_na", s);
    1095                 :          2 : }
    1096                 :            : 
    1097                 :            : static void
    1098                 :      15860 : encode_nested_actions(const struct ovnact_nest *on,
    1099                 :            :                       const struct ovnact_encode_params *ep,
    1100                 :            :                       enum action_opcode opcode,
    1101                 :            :                       struct ofpbuf *ofpacts)
    1102                 :            : {
    1103                 :            :     /* Convert nested actions into ofpacts. */
    1104                 :            :     uint64_t inner_ofpacts_stub[1024 / 8];
    1105                 :      15860 :     struct ofpbuf inner_ofpacts = OFPBUF_STUB_INITIALIZER(inner_ofpacts_stub);
    1106                 :      15860 :     ovnacts_encode(on->nested, on->nested_len, ep, &inner_ofpacts);
    1107                 :            : 
    1108                 :            :     /* Add a "controller" action with the actions nested inside "{...}",
    1109                 :            :      * converted to OpenFlow, as its userdata.  ovn-controller will convert the
    1110                 :            :      * packet to ARP or NA and then send the packet and actions back to the
    1111                 :            :      * switch inside an OFPT_PACKET_OUT message. */
    1112                 :      15860 :     size_t oc_offset = encode_start_controller_op(opcode, false, ofpacts);
    1113                 :      15860 :     ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size,
    1114                 :            :                                  ofpacts, OFP13_VERSION);
    1115                 :      15860 :     encode_finish_controller_op(oc_offset, ofpacts);
    1116                 :            : 
    1117                 :            :     /* Free memory. */
    1118                 :      15860 :     ofpbuf_uninit(&inner_ofpacts);
    1119                 :      15860 : }
    1120                 :            : 
    1121                 :            : static void
    1122                 :       2390 : encode_ARP(const struct ovnact_nest *on,
    1123                 :            :            const struct ovnact_encode_params *ep,
    1124                 :            :            struct ofpbuf *ofpacts)
    1125                 :            : {
    1126                 :       2390 :     encode_nested_actions(on, ep, ACTION_OPCODE_ARP, ofpacts);
    1127                 :       2390 : }
    1128                 :            : 
    1129                 :            : static void
    1130                 :      13470 : encode_ND_NA(const struct ovnact_nest *on,
    1131                 :            :              const struct ovnact_encode_params *ep,
    1132                 :            :              struct ofpbuf *ofpacts)
    1133                 :            : {
    1134                 :      13470 :     encode_nested_actions(on, ep, ACTION_OPCODE_ND_NA, ofpacts);
    1135                 :      13470 : }
    1136                 :            : 
    1137                 :            : static void
    1138                 :      15862 : free_nested_actions(struct ovnact_nest *on)
    1139                 :            : {
    1140                 :      15862 :     ovnacts_free(on->nested, on->nested_len);
    1141                 :      15862 :     free(on->nested);
    1142                 :      15862 : }
    1143                 :            : 
    1144                 :            : static void
    1145                 :       2391 : free_ARP(struct ovnact_nest *nest)
    1146                 :            : {
    1147                 :       2391 :     free_nested_actions(nest);
    1148                 :       2391 : }
    1149                 :            : 
    1150                 :            : static void
    1151                 :      13471 : free_ND_NA(struct ovnact_nest *nest)
    1152                 :            : {
    1153                 :      13471 :     free_nested_actions(nest);
    1154                 :      13471 : }
    1155                 :            : 
    1156                 :            : static void
    1157                 :       7191 : parse_get_mac_bind(struct action_context *ctx, int width,
    1158                 :            :                    struct ovnact_get_mac_bind *get_mac)
    1159                 :            : {
    1160                 :       7191 :     lexer_force_match(ctx->lexer, LEX_T_LPAREN);
    1161                 :       7191 :     action_parse_field(ctx, 0, false, &get_mac->port);
    1162                 :       7191 :     lexer_force_match(ctx->lexer, LEX_T_COMMA);
    1163                 :       7191 :     action_parse_field(ctx, width, false, &get_mac->ip);
    1164                 :       7191 :     lexer_force_match(ctx->lexer, LEX_T_RPAREN);
    1165                 :       7191 : }
    1166                 :            : 
    1167                 :            : static void
    1168                 :          8 : format_get_mac_bind(const struct ovnact_get_mac_bind *get_mac,
    1169                 :            :                     const char *name, struct ds *s)
    1170                 :            : {
    1171                 :          8 :     ds_put_format(s, "%s(", name);
    1172                 :          8 :     expr_field_format(&get_mac->port, s);
    1173                 :          8 :     ds_put_cstr(s, ", ");
    1174                 :          8 :     expr_field_format(&get_mac->ip, s);
    1175                 :          8 :     ds_put_cstr(s, ");");
    1176                 :          8 : }
    1177                 :            : 
    1178                 :            : static void
    1179                 :          4 : format_GET_ARP(const struct ovnact_get_mac_bind *get_mac, struct ds *s)
    1180                 :            : {
    1181                 :          4 :     format_get_mac_bind(get_mac, "get_arp", s);
    1182                 :          4 : }
    1183                 :            : 
    1184                 :            : static void
    1185                 :          4 : format_GET_ND(const struct ovnact_get_mac_bind *get_mac, struct ds *s)
    1186                 :            : {
    1187                 :          4 :     format_get_mac_bind(get_mac, "get_nd", s);
    1188                 :          4 : }
    1189                 :            : 
    1190                 :            : static void
    1191                 :       7171 : encode_get_mac(const struct ovnact_get_mac_bind *get_mac,
    1192                 :            :                enum mf_field_id ip_field,
    1193                 :            :                const struct ovnact_encode_params *ep,
    1194                 :            :                struct ofpbuf *ofpacts)
    1195                 :            : {
    1196                 :       7171 :     const struct arg args[] = {
    1197                 :       7171 :         { expr_resolve_field(&get_mac->port), MFF_LOG_OUTPORT },
    1198                 :       7171 :         { expr_resolve_field(&get_mac->ip), ip_field },
    1199                 :            :     };
    1200                 :       7171 :     encode_setup_args(args, ARRAY_SIZE(args), ofpacts);
    1201                 :            : 
    1202                 :       7171 :     put_load(0, MFF_ETH_DST, 0, 48, ofpacts);
    1203                 :       7171 :     emit_resubmit(ofpacts, ep->mac_bind_ptable);
    1204                 :            : 
    1205                 :       7171 :     encode_restore_args(args, ARRAY_SIZE(args), ofpacts);
    1206                 :       7171 : }
    1207                 :            : 
    1208                 :            : static void
    1209                 :       4780 : encode_GET_ARP(const struct ovnact_get_mac_bind *get_mac,
    1210                 :            :                const struct ovnact_encode_params *ep,
    1211                 :            :                struct ofpbuf *ofpacts)
    1212                 :            : {
    1213                 :       4780 :     encode_get_mac(get_mac, MFF_REG0, ep, ofpacts);
    1214                 :       4780 : }
    1215                 :            : 
    1216                 :            : static void
    1217                 :       2391 : encode_GET_ND(const struct ovnact_get_mac_bind *get_mac,
    1218                 :            :               const struct ovnact_encode_params *ep,
    1219                 :            :               struct ofpbuf *ofpacts)
    1220                 :            : {
    1221                 :       2391 :     encode_get_mac(get_mac, MFF_XXREG0, ep, ofpacts);
    1222                 :       2391 : }
    1223                 :            : 
    1224                 :            : static void
    1225                 :       4790 : free_GET_ARP(struct ovnact_get_mac_bind *get_mac OVS_UNUSED)
    1226                 :            : {
    1227                 :       4790 : }
    1228                 :            : 
    1229                 :            : static void
    1230                 :       2401 : free_GET_ND(struct ovnact_get_mac_bind *get_mac OVS_UNUSED)
    1231                 :            : {
    1232                 :       2401 : }
    1233                 :            : 
    1234                 :            : static void
    1235                 :      19650 : parse_put_mac_bind(struct action_context *ctx, int width,
    1236                 :            :                    struct ovnact_put_mac_bind *put_mac)
    1237                 :            : {
    1238                 :      19650 :     lexer_force_match(ctx->lexer, LEX_T_LPAREN);
    1239                 :      19650 :     action_parse_field(ctx, 0, false, &put_mac->port);
    1240                 :      19650 :     lexer_force_match(ctx->lexer, LEX_T_COMMA);
    1241                 :      19650 :     action_parse_field(ctx, width, false, &put_mac->ip);
    1242                 :      19650 :     lexer_force_match(ctx->lexer, LEX_T_COMMA);
    1243                 :      19650 :     action_parse_field(ctx, 48, false, &put_mac->mac);
    1244                 :      19650 :     lexer_force_match(ctx->lexer, LEX_T_RPAREN);
    1245                 :      19650 : }
    1246                 :            : 
    1247                 :            : static void
    1248                 :          4 : format_put_mac_bind(const struct ovnact_put_mac_bind *put_mac,
    1249                 :            :                     const char *name, struct ds *s)
    1250                 :            : {
    1251                 :          4 :     ds_put_format(s, "%s(", name);
    1252                 :          4 :     expr_field_format(&put_mac->port, s);
    1253                 :          4 :     ds_put_cstr(s, ", ");
    1254                 :          4 :     expr_field_format(&put_mac->ip, s);
    1255                 :          4 :     ds_put_cstr(s, ", ");
    1256                 :          4 :     expr_field_format(&put_mac->mac, s);
    1257                 :          4 :     ds_put_cstr(s, ");");
    1258                 :          4 : }
    1259                 :            : 
    1260                 :            : static void
    1261                 :          2 : format_PUT_ARP(const struct ovnact_put_mac_bind *put_mac, struct ds *s)
    1262                 :            : {
    1263                 :          2 :     format_put_mac_bind(put_mac, "put_arp", s);
    1264                 :          2 : }
    1265                 :            : 
    1266                 :            : static void
    1267                 :          2 : format_PUT_ND(const struct ovnact_put_mac_bind *put_mac, struct ds *s)
    1268                 :            : {
    1269                 :          2 :     format_put_mac_bind(put_mac, "put_nd", s);
    1270                 :          2 : }
    1271                 :            : 
    1272                 :            : static void
    1273                 :      19648 : encode_put_mac(const struct ovnact_put_mac_bind *put_mac,
    1274                 :            :                enum mf_field_id ip_field, enum action_opcode opcode,
    1275                 :            :                struct ofpbuf *ofpacts)
    1276                 :            : {
    1277                 :      19648 :     const struct arg args[] = {
    1278                 :      19648 :         { expr_resolve_field(&put_mac->port), MFF_LOG_INPORT },
    1279                 :      19648 :         { expr_resolve_field(&put_mac->ip), ip_field },
    1280                 :      19648 :         { expr_resolve_field(&put_mac->mac), MFF_ETH_SRC }
    1281                 :            :     };
    1282                 :      19648 :     encode_setup_args(args, ARRAY_SIZE(args), ofpacts);
    1283                 :      19648 :     encode_controller_op(opcode, ofpacts);
    1284                 :      19648 :     encode_restore_args(args, ARRAY_SIZE(args), ofpacts);
    1285                 :      19648 : }
    1286                 :            : 
    1287                 :            : static void
    1288                 :       2390 : encode_PUT_ARP(const struct ovnact_put_mac_bind *put_mac,
    1289                 :            :                const struct ovnact_encode_params *ep OVS_UNUSED,
    1290                 :            :                struct ofpbuf *ofpacts)
    1291                 :            : {
    1292                 :       2390 :     encode_put_mac(put_mac, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts);
    1293                 :       2390 : }
    1294                 :            : 
    1295                 :            : static void
    1296                 :      17258 : encode_PUT_ND(const struct ovnact_put_mac_bind *put_mac,
    1297                 :            :               const struct ovnact_encode_params *ep OVS_UNUSED,
    1298                 :            :               struct ofpbuf *ofpacts)
    1299                 :            : {
    1300                 :      17258 :     encode_put_mac(put_mac, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts);
    1301                 :      17258 : }
    1302                 :            : 
    1303                 :            : static void
    1304                 :       2391 : free_PUT_ARP(struct ovnact_put_mac_bind *put_mac OVS_UNUSED)
    1305                 :            : {
    1306                 :       2391 : }
    1307                 :            : 
    1308                 :            : static void
    1309                 :      17259 : free_PUT_ND(struct ovnact_put_mac_bind *put_mac OVS_UNUSED)
    1310                 :            : {
    1311                 :      17259 : }
    1312                 :            : 
    1313                 :            : static void
    1314                 :        591 : parse_dhcp_opt(struct action_context *ctx, struct ovnact_dhcp_option *o,
    1315                 :            :                bool v6)
    1316                 :            : {
    1317         [ +  + ]:        591 :     if (ctx->lexer->token.type != LEX_T_ID) {
    1318                 :          2 :         lexer_syntax_error(ctx->lexer, NULL);
    1319                 :          2 :         return;
    1320                 :            :     }
    1321                 :            : 
    1322         [ +  + ]:        589 :     const char *name = v6 ? "DHCPv6" : "DHCPv4";
    1323         [ +  + ]:        589 :     const struct hmap *map = v6 ? ctx->pp->dhcpv6_opts : ctx->pp->dhcp_opts;
    1324                 :        589 :     o->option = dhcp_opts_find(map, ctx->lexer->token.s);
    1325         [ +  + ]:        589 :     if (!o->option) {
    1326                 :          4 :         lexer_syntax_error(ctx->lexer, "expecting %s option name", name);
    1327                 :          4 :         return;
    1328                 :            :     }
    1329                 :        585 :     lexer_get(ctx->lexer);
    1330                 :            : 
    1331         [ -  + ]:        585 :     if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
    1332                 :          0 :         return;
    1333                 :            :     }
    1334                 :            : 
    1335         [ -  + ]:        585 :     if (!expr_constant_set_parse(ctx->lexer, &o->value)) {
    1336                 :          0 :         memset(&o->value, 0, sizeof o->value);
    1337                 :          0 :         return;
    1338                 :            :     }
    1339                 :            : 
    1340         [ +  + ]:        585 :     if (!strcmp(o->option->type, "str")) {
    1341         [ +  + ]:          6 :         if (o->value.type != EXPR_C_STRING) {
    1342                 :          2 :             lexer_error(ctx->lexer, "%s option %s requires string value.",
    1343                 :          2 :                         name, o->option->name);
    1344                 :          2 :             return;
    1345                 :            :         }
    1346                 :            :     } else {
    1347         [ +  + ]:        579 :         if (o->value.type != EXPR_C_INTEGER) {
    1348                 :          2 :             lexer_error(ctx->lexer, "%s option %s requires numeric value.",
    1349                 :          2 :                         name, o->option->name);
    1350                 :          2 :             return;
    1351                 :            :         }
    1352                 :            :     }
    1353                 :            : }
    1354                 :            : 
    1355                 :            : static const struct ovnact_dhcp_option *
    1356                 :        179 : find_offerip(const struct ovnact_dhcp_option *options, size_t n)
    1357                 :            : {
    1358         [ +  + ]:        180 :     for (const struct ovnact_dhcp_option *o = options; o < &options[n]; o++) {
    1359         [ +  + ]:        178 :         if (o->option->code == 0) {
    1360                 :        177 :             return o;
    1361                 :            :         }
    1362                 :            :     }
    1363                 :          2 :     return NULL;
    1364                 :            : }
    1365                 :            : 
    1366                 :            : static void
    1367                 :        167 : free_dhcp_options(struct ovnact_dhcp_option *options, size_t n)
    1368                 :            : {
    1369         [ +  + ]:        758 :     for (struct ovnact_dhcp_option *o = options; o < &options[n]; o++) {
    1370                 :        591 :         expr_constant_set_destroy(&o->value);
    1371                 :            :     }
    1372                 :        167 :     free(options);
    1373                 :        167 : }
    1374                 :            : 
    1375                 :            : /* Parses the "put_dhcp_opts" and "put_dhcpv6_opts" actions.
    1376                 :            :  *
    1377                 :            :  * The caller has already consumed "<dst> =", so this just parses the rest. */
    1378                 :            : static void
    1379                 :        167 : parse_put_dhcp_opts(struct action_context *ctx,
    1380                 :            :                     const struct expr_field *dst,
    1381                 :            :                     struct ovnact_put_dhcp_opts *pdo)
    1382                 :            : {
    1383                 :        167 :     lexer_get(ctx->lexer); /* Skip put_dhcp[v6]_opts. */
    1384                 :        167 :     lexer_get(ctx->lexer); /* Skip '('. */
    1385                 :            : 
    1386                 :            :     /* Validate that the destination is a 1-bit, modifiable field. */
    1387                 :        167 :     char *error = expr_type_check(dst, 1, true);
    1388         [ +  + ]:        167 :     if (error) {
    1389                 :          1 :         lexer_error(ctx->lexer, "%s", error);
    1390                 :          1 :         free(error);
    1391                 :         13 :         return;
    1392                 :            :     }
    1393                 :        166 :     pdo->dst = *dst;
    1394                 :            : 
    1395                 :        166 :     size_t allocated_options = 0;
    1396         [ +  + ]:        747 :     while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
    1397         [ +  + ]:        591 :         if (pdo->n_options >= allocated_options) {
    1398                 :        495 :             pdo->options = x2nrealloc(pdo->options, &allocated_options,
    1399                 :            :                                       sizeof *pdo->options);
    1400                 :            :         }
    1401                 :            : 
    1402                 :        591 :         struct ovnact_dhcp_option *o = &pdo->options[pdo->n_options++];
    1403                 :        591 :         memset(o, 0, sizeof *o);
    1404                 :        591 :         parse_dhcp_opt(ctx, o, pdo->ovnact.type == OVNACT_PUT_DHCPV6_OPTS);
    1405         [ +  + ]:        591 :         if (ctx->lexer->error) {
    1406                 :         10 :             return;
    1407                 :            :         }
    1408                 :            : 
    1409                 :        581 :         lexer_match(ctx->lexer, LEX_T_COMMA);
    1410                 :            :     }
    1411                 :            : 
    1412         [ +  + ]:        156 :     if (pdo->ovnact.type == OVNACT_PUT_DHCPV4_OPTS
    1413         [ +  + ]:         92 :         && !find_offerip(pdo->options, pdo->n_options)) {
    1414                 :        156 :         lexer_error(ctx->lexer,
    1415                 :            :                     "put_dhcp_opts requires offerip to be specified.");
    1416                 :          2 :         return;
    1417                 :            :     }
    1418                 :            : }
    1419                 :            : 
    1420                 :            : static void
    1421                 :         14 : format_put_dhcp_opts(const char *name,
    1422                 :            :                      const struct ovnact_put_dhcp_opts *pdo, struct ds *s)
    1423                 :            : {
    1424                 :         14 :     expr_field_format(&pdo->dst, s);
    1425                 :         14 :     ds_put_format(s, " = %s(", name);
    1426         [ +  + ]:         56 :     for (const struct ovnact_dhcp_option *o = pdo->options;
    1427                 :         42 :          o < &pdo->options[pdo->n_options]; o++) {
    1428         [ +  + ]:         42 :         if (o != pdo->options) {
    1429                 :         30 :             ds_put_cstr(s, ", ");
    1430                 :            :         }
    1431                 :         42 :         ds_put_format(s, "%s = ", o->option->name);
    1432                 :         42 :         expr_constant_set_format(&o->value, s);
    1433                 :            :     }
    1434                 :         14 :     ds_put_cstr(s, ");");
    1435                 :         14 : }
    1436                 :            : 
    1437                 :            : static void
    1438                 :          6 : format_PUT_DHCPV4_OPTS(const struct ovnact_put_dhcp_opts *pdo, struct ds *s)
    1439                 :            : {
    1440                 :          6 :     format_put_dhcp_opts("put_dhcp_opts", pdo, s);
    1441                 :          6 : }
    1442                 :            : 
    1443                 :            : static void
    1444                 :          8 : format_PUT_DHCPV6_OPTS(const struct ovnact_put_dhcp_opts *pdo, struct ds *s)
    1445                 :            : {
    1446                 :          8 :     format_put_dhcp_opts("put_dhcpv6_opts", pdo, s);
    1447                 :          8 : }
    1448                 :            : 
    1449                 :            : static void
    1450                 :        350 : encode_put_dhcpv4_option(const struct ovnact_dhcp_option *o,
    1451                 :            :                          struct ofpbuf *ofpacts)
    1452                 :            : {
    1453                 :        350 :     uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
    1454                 :        350 :     opt_header[0] = o->option->code;
    1455                 :            : 
    1456                 :        350 :     const union expr_constant *c = o->value.values;
    1457                 :        350 :     size_t n_values = o->value.n_values;
    1458 [ +  + ][ +  + ]:        350 :     if (!strcmp(o->option->type, "bool") ||
    1459                 :        347 :         !strcmp(o->option->type, "uint8")) {
    1460                 :          4 :         opt_header[1] = 1;
    1461                 :          4 :         ofpbuf_put(ofpacts, &c->value.u8_val, 1);
    1462         [ +  + ]:        346 :     } else if (!strcmp(o->option->type, "uint16")) {
    1463                 :          2 :         opt_header[1] = 2;
    1464                 :          2 :         ofpbuf_put(ofpacts, &c->value.be16_int, 2);
    1465         [ +  + ]:        344 :     } else if (!strcmp(o->option->type, "uint32")) {
    1466                 :         84 :         opt_header[1] = 4;
    1467                 :         84 :         ofpbuf_put(ofpacts, &c->value.be32_int, 4);
    1468         [ +  + ]:        260 :     } else if (!strcmp(o->option->type, "ipv4")) {
    1469                 :        258 :         opt_header[1] = n_values * sizeof(ovs_be32);
    1470         [ +  + ]:        517 :         for (size_t i = 0; i < n_values; i++) {
    1471                 :        259 :             ofpbuf_put(ofpacts, &c[i].value.ipv4, sizeof(ovs_be32));
    1472                 :            :         }
    1473         [ +  + ]:          2 :     } else if (!strcmp(o->option->type, "static_routes")) {
    1474                 :          1 :         size_t no_of_routes = n_values;
    1475         [ -  + ]:          1 :         if (no_of_routes % 2) {
    1476                 :          0 :             no_of_routes -= 1;
    1477                 :            :         }
    1478                 :          1 :         opt_header[1] = 0;
    1479                 :            : 
    1480                 :            :         /* Calculating the length of this option first because when
    1481                 :            :          * we call ofpbuf_put, it might reallocate the buffer if the
    1482                 :            :          * tail room is short making "opt_header" pointer invalid.
    1483                 :            :          * So running the for loop twice.
    1484                 :            :          */
    1485         [ +  + ]:          4 :         for (size_t i = 0; i < no_of_routes; i += 2) {
    1486                 :          3 :             uint8_t plen = 32;
    1487         [ +  - ]:          3 :             if (c[i].masked) {
    1488                 :          3 :                 plen = (uint8_t) ip_count_cidr_bits(c[i].mask.ipv4);
    1489                 :            :             }
    1490                 :          3 :             opt_header[1] += (1 + (plen / 8) + sizeof(ovs_be32)) ;
    1491                 :            :         }
    1492                 :            : 
    1493                 :            :         /* Copied from RFC 3442. Please refer to this RFC for the format of
    1494                 :            :          * the classless static route option.
    1495                 :            :          *
    1496                 :            :          *  The following table contains some examples of how various subnet
    1497                 :            :          *  number/mask combinations can be encoded:
    1498                 :            :          *
    1499                 :            :          *  Subnet number   Subnet mask      Destination descriptor
    1500                 :            :          *  0               0                0
    1501                 :            :          *  10.0.0.0        255.0.0.0        8.10
    1502                 :            :          *  10.0.0.0        255.255.255.0    24.10.0.0
    1503                 :            :          *  10.17.0.0       255.255.0.0      16.10.17
    1504                 :            :          *  10.27.129.0     255.255.255.0    24.10.27.129
    1505                 :            :          *  10.229.0.128    255.255.255.128  25.10.229.0.128
    1506                 :            :          *  10.198.122.47   255.255.255.255  32.10.198.122.47
    1507                 :            :          */
    1508                 :            : 
    1509         [ +  + ]:          4 :         for (size_t i = 0; i < no_of_routes; i += 2) {
    1510                 :          3 :             uint8_t plen = 32;
    1511         [ +  - ]:          3 :             if (c[i].masked) {
    1512                 :          3 :                 plen = ip_count_cidr_bits(c[i].mask.ipv4);
    1513                 :            :             }
    1514                 :          3 :             ofpbuf_put(ofpacts, &plen, 1);
    1515                 :          3 :             ofpbuf_put(ofpacts, &c[i].value.ipv4, plen / 8);
    1516                 :          3 :             ofpbuf_put(ofpacts, &c[i + 1].value.ipv4,
    1517                 :            :                        sizeof(ovs_be32));
    1518                 :            :         }
    1519         [ +  - ]:          1 :     } else if (!strcmp(o->option->type, "str")) {
    1520                 :          1 :         opt_header[1] = strlen(c->string);
    1521                 :          1 :         ofpbuf_put(ofpacts, c->string, opt_header[1]);
    1522                 :            :     }
    1523                 :        350 : }
    1524                 :            : 
    1525                 :            : static void
    1526                 :        116 : encode_put_dhcpv6_option(const struct ovnact_dhcp_option *o,
    1527                 :            :                          struct ofpbuf *ofpacts)
    1528                 :            : {
    1529                 :        116 :     struct dhcp_opt6_header *opt = ofpbuf_put_uninit(ofpacts, sizeof *opt);
    1530                 :        116 :     opt->code = o->option->code;
    1531                 :            : 
    1532                 :        116 :     const union expr_constant *c = o->value.values;
    1533                 :        116 :     size_t n_values = o->value.n_values;
    1534         [ +  + ]:        116 :     if (!strcmp(o->option->type, "ipv6")) {
    1535                 :         58 :         opt->len = n_values * sizeof(struct in6_addr);
    1536         [ +  + ]:        117 :         for (size_t i = 0; i < n_values; i++) {
    1537                 :         59 :             ofpbuf_put(ofpacts, &c[i].value.ipv6, sizeof(struct in6_addr));
    1538                 :            :         }
    1539         [ +  + ]:         58 :     } else if (!strcmp(o->option->type, "mac")) {
    1540                 :         57 :         opt->len = sizeof(struct eth_addr);
    1541                 :         57 :         ofpbuf_put(ofpacts, &c->value.mac, opt->len);
    1542         [ +  - ]:          1 :     } else if (!strcmp(o->option->type, "str")) {
    1543                 :          1 :         opt->len = strlen(c->string);
    1544                 :          1 :         ofpbuf_put(ofpacts, c->string, opt->len);
    1545                 :            :     }
    1546                 :        116 : }
    1547                 :            : 
    1548                 :            : static void
    1549                 :         87 : encode_PUT_DHCPV4_OPTS(const struct ovnact_put_dhcp_opts *pdo,
    1550                 :            :                        const struct ovnact_encode_params *ep OVS_UNUSED,
    1551                 :            :                        struct ofpbuf *ofpacts)
    1552                 :            : {
    1553                 :         87 :     struct mf_subfield dst = expr_resolve_field(&pdo->dst);
    1554                 :            : 
    1555                 :         87 :     size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_PUT_DHCP_OPTS,
    1556                 :            :                                                   true, ofpacts);
    1557                 :         87 :     nx_put_header(ofpacts, dst.field->id, OFP13_VERSION, false);
    1558                 :         87 :     ovs_be32 ofs = htonl(dst.ofs);
    1559                 :         87 :     ofpbuf_put(ofpacts, &ofs, sizeof ofs);
    1560                 :            : 
    1561                 :            :     /* Encode the offerip option first, because it's a special case and needs
    1562                 :            :      * to be first in the actual DHCP response, and then encode the rest
    1563                 :            :      * (skipping offerip the second time around). */
    1564                 :         87 :     const struct ovnact_dhcp_option *offerip_opt = find_offerip(
    1565                 :         87 :         pdo->options, pdo->n_options);
    1566                 :         87 :     ovs_be32 offerip = offerip_opt->value.values[0].value.ipv4;
    1567                 :         87 :     ofpbuf_put(ofpacts, &offerip, sizeof offerip);
    1568                 :            : 
    1569         [ +  + ]:        524 :     for (const struct ovnact_dhcp_option *o = pdo->options;
    1570                 :        437 :          o < &pdo->options[pdo->n_options]; o++) {
    1571         [ +  + ]:        437 :         if (o != offerip_opt) {
    1572                 :        350 :             encode_put_dhcpv4_option(o, ofpacts);
    1573                 :            :         }
    1574                 :            :     }
    1575                 :            : 
    1576                 :         87 :     encode_finish_controller_op(oc_offset, ofpacts);
    1577                 :         87 : }
    1578                 :            : 
    1579                 :            : static void
    1580                 :         60 : encode_PUT_DHCPV6_OPTS(const struct ovnact_put_dhcp_opts *pdo,
    1581                 :            :                        const struct ovnact_encode_params *ep OVS_UNUSED,
    1582                 :            :                        struct ofpbuf *ofpacts)
    1583                 :            : {
    1584                 :         60 :     struct mf_subfield dst = expr_resolve_field(&pdo->dst);
    1585                 :            : 
    1586                 :         60 :     size_t oc_offset = encode_start_controller_op(
    1587                 :            :         ACTION_OPCODE_PUT_DHCPV6_OPTS, true, ofpacts);
    1588                 :         60 :     nx_put_header(ofpacts, dst.field->id, OFP13_VERSION, false);
    1589                 :         60 :     ovs_be32 ofs = htonl(dst.ofs);
    1590                 :         60 :     ofpbuf_put(ofpacts, &ofs, sizeof ofs);
    1591                 :            : 
    1592         [ +  + ]:        176 :     for (const struct ovnact_dhcp_option *o = pdo->options;
    1593                 :        116 :          o < &pdo->options[pdo->n_options]; o++) {
    1594                 :        116 :         encode_put_dhcpv6_option(o, ofpacts);
    1595                 :            :     }
    1596                 :            : 
    1597                 :         60 :     encode_finish_controller_op(oc_offset, ofpacts);
    1598                 :         60 : }
    1599                 :            : 
    1600                 :            : static void
    1601                 :        167 : free_put_dhcp_opts(struct ovnact_put_dhcp_opts *pdo)
    1602                 :            : {
    1603                 :        167 :     free_dhcp_options(pdo->options, pdo->n_options);
    1604                 :        167 : }
    1605                 :            : 
    1606                 :            : static void
    1607                 :         98 : free_PUT_DHCPV4_OPTS(struct ovnact_put_dhcp_opts *pdo)
    1608                 :            : {
    1609                 :         98 :     free_put_dhcp_opts(pdo);
    1610                 :         98 : }
    1611                 :            : 
    1612                 :            : static void
    1613                 :         69 : free_PUT_DHCPV6_OPTS(struct ovnact_put_dhcp_opts *pdo)
    1614                 :            : {
    1615                 :         69 :     free_put_dhcp_opts(pdo);
    1616                 :         69 : }
    1617                 :            : 
    1618                 :            : /* Parses an assignment or exchange or put_dhcp_opts action. */
    1619                 :            : static void
    1620                 :     857308 : parse_set_action(struct action_context *ctx)
    1621                 :            : {
    1622                 :            :     struct expr_field lhs;
    1623         [ +  + ]:     857308 :     if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, &lhs, &ctx->prereqs)) {
    1624                 :          6 :         return;
    1625                 :            :     }
    1626                 :            : 
    1627         [ +  + ]:     857302 :     if (lexer_match(ctx->lexer, LEX_T_EXCHANGE)) {
    1628                 :      24974 :         parse_assignment_action(ctx, true, &lhs);
    1629         [ +  + ]:     832328 :     } else if (lexer_match(ctx->lexer, LEX_T_EQUALS)) {
    1630         [ +  + ]:     832327 :         if (ctx->lexer->token.type != LEX_T_ID) {
    1631                 :     622053 :             parse_LOAD(ctx, &lhs);
    1632         [ +  + ]:     210274 :         } else if (!strcmp(ctx->lexer->token.s, "put_dhcp_opts")
    1633         [ +  - ]:         98 :                    && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
    1634                 :         98 :             parse_put_dhcp_opts(ctx, &lhs, ovnact_put_PUT_DHCPV4_OPTS(
    1635                 :            :                                     ctx->ovnacts));
    1636         [ +  + ]:     210176 :         } else if (!strcmp(ctx->lexer->token.s, "put_dhcpv6_opts")
    1637         [ +  - ]:         69 :                    && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
    1638                 :         69 :             parse_put_dhcp_opts(ctx, &lhs, ovnact_put_PUT_DHCPV6_OPTS(
    1639                 :            :                                     ctx->ovnacts));
    1640                 :            :         } else {
    1641                 :     832327 :             parse_assignment_action(ctx, false, &lhs);
    1642                 :            :         }
    1643                 :            :     } else {
    1644                 :     857302 :         lexer_syntax_error(ctx->lexer, "expecting `=' or `<->'");
    1645                 :            :     }
    1646                 :            : }
    1647                 :            : 
    1648                 :            : static bool
    1649                 :    1485014 : parse_action(struct action_context *ctx)
    1650                 :            : {
    1651         [ +  + ]:    1485014 :     if (ctx->lexer->token.type != LEX_T_ID) {
    1652                 :          2 :         lexer_syntax_error(ctx->lexer, NULL);
    1653                 :          2 :         return false;
    1654                 :            :     }
    1655                 :            : 
    1656                 :    1485012 :     enum lex_type lookahead = lexer_lookahead(ctx->lexer);
    1657 [ +  + ][ +  + ]:    1485012 :     if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_EXCHANGE
    1658         [ +  + ]:     628017 :         || lookahead == LEX_T_LSQUARE) {
    1659                 :     857308 :         parse_set_action(ctx);
    1660         [ +  + ]:     627704 :     } else if (lexer_match_id(ctx->lexer, "next")) {
    1661                 :     334192 :         parse_NEXT(ctx);
    1662         [ +  + ]:     293512 :     } else if (lexer_match_id(ctx->lexer, "output")) {
    1663                 :     188737 :         ovnact_put_OUTPUT(ctx->ovnacts);
    1664         [ +  + ]:     104775 :     } else if (lexer_match_id(ctx->lexer, "ip.ttl")) {
    1665                 :      25814 :         parse_DEC_TTL(ctx);
    1666         [ +  + ]:      78961 :     } else if (lexer_match_id(ctx->lexer, "ct_next")) {
    1667                 :      11931 :         parse_CT_NEXT(ctx);
    1668         [ +  + ]:      67030 :     } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
    1669                 :      11929 :         parse_CT_COMMIT(ctx);
    1670         [ +  + ]:      55101 :     } else if (lexer_match_id(ctx->lexer, "ct_dnat")) {
    1671                 :        371 :         parse_CT_DNAT(ctx);
    1672         [ +  + ]:      54730 :     } else if (lexer_match_id(ctx->lexer, "ct_snat")) {
    1673                 :         54 :         parse_CT_SNAT(ctx);
    1674         [ +  + ]:      54676 :     } else if (lexer_match_id(ctx->lexer, "ct_lb")) {
    1675                 :      11970 :         parse_ct_lb_action(ctx);
    1676         [ +  + ]:      42706 :     } else if (lexer_match_id(ctx->lexer, "arp")) {
    1677                 :       2391 :         parse_ARP(ctx);
    1678         [ +  + ]:      40315 :     } else if (lexer_match_id(ctx->lexer, "nd_na")) {
    1679                 :      13471 :         parse_ND_NA(ctx);
    1680         [ +  + ]:      26844 :     } else if (lexer_match_id(ctx->lexer, "get_arp")) {
    1681                 :       4790 :         parse_get_mac_bind(ctx, 32, ovnact_put_GET_ARP(ctx->ovnacts));
    1682         [ +  + ]:      22054 :     } else if (lexer_match_id(ctx->lexer, "put_arp")) {
    1683                 :       2391 :         parse_put_mac_bind(ctx, 32, ovnact_put_PUT_ARP(ctx->ovnacts));
    1684         [ +  + ]:      19663 :     } else if (lexer_match_id(ctx->lexer, "get_nd")) {
    1685                 :       2401 :         parse_get_mac_bind(ctx, 128, ovnact_put_GET_ND(ctx->ovnacts));
    1686         [ +  + ]:      17262 :     } else if (lexer_match_id(ctx->lexer, "put_nd")) {
    1687                 :      17259 :         parse_put_mac_bind(ctx, 128, ovnact_put_PUT_ND(ctx->ovnacts));
    1688                 :            :     } else {
    1689                 :          3 :         lexer_syntax_error(ctx->lexer, "expecting action");
    1690                 :            :     }
    1691                 :    1485012 :     lexer_force_match(ctx->lexer, LEX_T_SEMICOLON);
    1692                 :    1485012 :     return !ctx->lexer->error;
    1693                 :            : }
    1694                 :            : 
    1695                 :            : static void
    1696                 :     631163 : parse_actions(struct action_context *ctx)
    1697                 :            : {
    1698                 :            :     /* "drop;" by itself is a valid (empty) set of actions, but it can't be
    1699                 :            :      * combined with other actions because that doesn't make sense. */
    1700         [ +  + ]:     631163 :     if (ctx->lexer->token.type == LEX_T_ID
    1701         [ +  + ]:     631162 :         && !strcmp(ctx->lexer->token.s, "drop")
    1702         [ +  - ]:      76630 :         && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) {
    1703                 :      76630 :         lexer_get(ctx->lexer);  /* Skip "drop". */
    1704                 :      76630 :         lexer_get(ctx->lexer);  /* Skip ";". */
    1705                 :      76630 :         lexer_force_end(ctx->lexer);
    1706                 :      76630 :         return;
    1707                 :            :     }
    1708                 :            : 
    1709         [ +  + ]:    1933233 :     while (ctx->lexer->token.type != LEX_T_END) {
    1710         [ +  + ]:    1378772 :         if (!parse_action(ctx)) {
    1711                 :         72 :             return;
    1712                 :            :         }
    1713                 :            :     }
    1714                 :            : }
    1715                 :            : 
    1716                 :            : /* Parses OVN actions, in the format described for the "actions" column in the
    1717                 :            :  * Logical_Flow table in ovn-sb(5), and appends the parsed versions of the
    1718                 :            :  * actions to 'ovnacts' as "struct ovnact"s.  The caller must eventually free
    1719                 :            :  * the parsed ovnacts with ovnacts_free().
    1720                 :            :  *
    1721                 :            :  * 'pp' provides most of the parameters for translation.
    1722                 :            :  *
    1723                 :            :  * Some actions add extra requirements (prerequisites) to the flow's match.  If
    1724                 :            :  * so, this function sets '*prereqsp' to the actions' prerequisites; otherwise,
    1725                 :            :  * it sets '*prereqsp' to NULL.  The caller owns '*prereqsp' and must
    1726                 :            :  * eventually free it.
    1727                 :            :  *
    1728                 :            :  * Returns true if successful, false if an error occurred.  Upon return,
    1729                 :            :  * returns true if and only if lexer->error is NULL.
    1730                 :            :  */
    1731                 :            : bool
    1732                 :     631163 : ovnacts_parse(struct lexer *lexer, const struct ovnact_parse_params *pp,
    1733                 :            :               struct ofpbuf *ovnacts, struct expr **prereqsp)
    1734                 :            : {
    1735                 :     631163 :     size_t ovnacts_start = ovnacts->size;
    1736                 :            : 
    1737                 :     631163 :     struct action_context ctx = {
    1738                 :            :         .pp = pp,
    1739                 :            :         .lexer = lexer,
    1740                 :            :         .ovnacts = ovnacts,
    1741                 :            :         .prereqs = NULL,
    1742                 :            :     };
    1743         [ +  - ]:     631163 :     if (!lexer->error) {
    1744                 :     631163 :         parse_actions(&ctx);
    1745                 :            :     }
    1746                 :            : 
    1747         [ +  + ]:     631163 :     if (!lexer->error) {
    1748                 :     631090 :         *prereqsp = ctx.prereqs;
    1749                 :     631090 :         return true;
    1750                 :            :     } else {
    1751                 :         73 :         ofpbuf_pull(ovnacts, ovnacts_start);
    1752                 :         73 :         ovnacts_free(ovnacts->data, ovnacts->size);
    1753                 :         73 :         ofpbuf_push_uninit(ovnacts, ovnacts_start);
    1754                 :            : 
    1755                 :         73 :         ovnacts->size = ovnacts_start;
    1756                 :         73 :         expr_destroy(ctx.prereqs);
    1757                 :         73 :         *prereqsp = NULL;
    1758                 :     631163 :         return false;
    1759                 :            :     }
    1760                 :            : }
    1761                 :            : 
    1762                 :            : /* Like ovnacts_parse(), but the actions are taken from 's'. */
    1763                 :            : char * OVS_WARN_UNUSED_RESULT
    1764                 :     631163 : ovnacts_parse_string(const char *s, const struct ovnact_parse_params *pp,
    1765                 :            :                      struct ofpbuf *ofpacts, struct expr **prereqsp)
    1766                 :            : {
    1767                 :            :     struct lexer lexer;
    1768                 :            : 
    1769                 :     631163 :     lexer_init(&lexer, s);
    1770                 :     631163 :     lexer_get(&lexer);
    1771                 :     631163 :     ovnacts_parse(&lexer, pp, ofpacts, prereqsp);
    1772                 :     631163 :     char *error = lexer_steal_error(&lexer);
    1773                 :     631163 :     lexer_destroy(&lexer);
    1774                 :            : 
    1775                 :     631163 :     return error;
    1776                 :            : }
    1777                 :            : 
    1778                 :            : /* Formatting ovnacts. */
    1779                 :            : 
    1780                 :            : static void
    1781                 :        136 : ovnact_format(const struct ovnact *a, struct ds *s)
    1782                 :            : {
    1783   [ +  +  +  +  :        136 :     switch (a->type) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                      - ]
    1784                 :            : #define OVNACT(ENUM, STRUCT)                                            \
    1785                 :            :         case OVNACT_##ENUM:                                             \
    1786                 :            :             format_##ENUM(ALIGNED_CAST(const struct STRUCT *, a), s);   \
    1787                 :            :             break;
    1788                 :        136 :         OVNACTS
    1789                 :            : #undef OVNACT
    1790                 :            :     default:
    1791                 :          0 :         OVS_NOT_REACHED();
    1792                 :            :     }
    1793                 :        136 : }
    1794                 :            : 
    1795                 :            : /* Appends a string representing the 'ovnacts_len' bytes of ovnacts in
    1796                 :            :  * 'ovnacts' to 'string'. */
    1797                 :            : void
    1798                 :        122 : ovnacts_format(const struct ovnact *ovnacts, size_t ovnacts_len,
    1799                 :            :                struct ds *string)
    1800                 :            : {
    1801         [ +  + ]:        122 :     if (!ovnacts_len) {
    1802                 :          2 :         ds_put_cstr(string, "drop;");
    1803                 :            :     } else {
    1804                 :            :         const struct ovnact *a;
    1805                 :            : 
    1806         [ +  + ]:        256 :         OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
    1807         [ +  + ]:        136 :             if (a != ovnacts) {
    1808                 :         16 :                 ds_put_char(string, ' ');
    1809                 :            :             }
    1810                 :        136 :             ovnact_format(a, string);
    1811                 :            :         }
    1812                 :            :     }
    1813                 :        122 : }
    1814                 :            : 
    1815                 :            : /* Encoding ovnacts to OpenFlow. */
    1816                 :            : 
    1817                 :            : static void
    1818                 :    1484871 : ovnact_encode(const struct ovnact *a, const struct ovnact_encode_params *ep,
    1819                 :            :               struct ofpbuf *ofpacts)
    1820                 :            : {
    1821   [ +  +  +  +  :    1484871 :     switch (a->type) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                      - ]
    1822                 :            : #define OVNACT(ENUM, STRUCT)                                            \
    1823                 :            :         case OVNACT_##ENUM:                                             \
    1824                 :            :             encode_##ENUM(ALIGNED_CAST(const struct STRUCT *, a),       \
    1825                 :            :                           ep, ofpacts);                                 \
    1826                 :            :             break;
    1827                 :    1484871 :         OVNACTS
    1828                 :            : #undef OVNACT
    1829                 :            :     default:
    1830                 :          0 :         OVS_NOT_REACHED();
    1831                 :            :     }
    1832                 :    1484871 : }
    1833                 :            : 
    1834                 :            : /* Appends ofpacts to 'ofpacts' that represent the actions in the 'ovnacts_len'
    1835                 :            :  * bytes of actions starting at 'ovnacts'. */
    1836                 :            : void
    1837                 :     646891 : ovnacts_encode(const struct ovnact *ovnacts, size_t ovnacts_len,
    1838                 :            :                const struct ovnact_encode_params *ep,
    1839                 :            :                struct ofpbuf *ofpacts)
    1840                 :            : {
    1841         [ +  + ]:     646891 :     if (ovnacts) {
    1842                 :            :         const struct ovnact *a;
    1843                 :            : 
    1844         [ +  + ]:    2131761 :         OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
    1845                 :    1484871 :             ovnact_encode(a, ep, ofpacts);
    1846                 :            :         }
    1847                 :            :     }
    1848                 :     646891 : }
    1849                 :            : 
    1850                 :            : /* Freeing ovnacts. */
    1851                 :            : 
    1852                 :            : static void
    1853                 :    1484982 : ovnact_free(struct ovnact *a)
    1854                 :            : {
    1855   [ +  +  +  +  :    1484982 :     switch (a->type) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
                      - ]
    1856                 :            : #define OVNACT(ENUM, STRUCT)                                            \
    1857                 :            :         case OVNACT_##ENUM:                                             \
    1858                 :            :             free_##ENUM(ALIGNED_CAST(struct STRUCT *, a));              \
    1859                 :            :             break;
    1860                 :    1484982 :         OVNACTS
    1861                 :            : #undef OVNACT
    1862                 :            :     default:
    1863                 :          0 :         OVS_NOT_REACHED();
    1864                 :            :     }
    1865                 :    1484982 : }
    1866                 :            : 
    1867                 :            : /* Frees each of the actions in the 'ovnacts_len' bytes of actions starting at
    1868                 :            :  * 'ovnacts'.
    1869                 :            :  *
    1870                 :            :  * Does not call free(ovnacts); the caller must do so if desirable. */
    1871                 :            : void
    1872                 :     647098 : ovnacts_free(struct ovnact *ovnacts, size_t ovnacts_len)
    1873                 :            : {
    1874         [ +  + ]:     647098 :     if (ovnacts) {
    1875                 :            :         struct ovnact *a;
    1876                 :            : 
    1877         [ +  + ]:    2132024 :         OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
    1878                 :    1484982 :             ovnact_free(a);
    1879                 :            :         }
    1880                 :            :     }
    1881                 :     647098 : }

Generated by: LCOV version 1.12