LCOV - code coverage report
Current view: top level - lib - dp-packet.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 155 184 84.2 %
Date: 2016-09-14 01:02:56 Functions: 26 32 81.2 %
Branches: 31 51 60.8 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 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 <stdlib.h>
      19                 :            : #include <string.h>
      20                 :            : #include "openvswitch/dynamic-string.h"
      21                 :            : #include "netdev-dpdk.h"
      22                 :            : #include "dp-packet.h"
      23                 :            : #include "util.h"
      24                 :            : 
      25                 :            : static void
      26                 :     100917 : dp_packet_init__(struct dp_packet *b, size_t allocated, enum dp_packet_source source)
      27                 :            : {
      28                 :     100917 :     dp_packet_set_allocated(b, allocated);
      29                 :     100917 :     b->source = source;
      30                 :     100917 :     dp_packet_reset_offsets(b);
      31                 :     100917 :     pkt_metadata_init(&b->md, 0);
      32                 :     100917 :     dp_packet_rss_invalidate(b);
      33                 :     100917 :     dp_packet_reset_cutlen(b);
      34                 :     100917 : }
      35                 :            : 
      36                 :            : static void
      37                 :     100917 : dp_packet_use__(struct dp_packet *b, void *base, size_t allocated,
      38                 :            :              enum dp_packet_source source)
      39                 :            : {
      40                 :     100917 :     dp_packet_set_base(b, base);
      41                 :     100917 :     dp_packet_set_data(b, base);
      42                 :     100917 :     dp_packet_set_size(b, 0);
      43                 :            : 
      44                 :     100917 :     dp_packet_init__(b, allocated, source);
      45                 :     100917 : }
      46                 :            : 
      47                 :            : /* Initializes 'b' as an empty dp_packet that contains the 'allocated' bytes of
      48                 :            :  * memory starting at 'base'.  'base' should be the first byte of a region
      49                 :            :  * obtained from malloc().  It will be freed (with free()) if 'b' is resized or
      50                 :            :  * freed. */
      51                 :            : void
      52                 :      69902 : dp_packet_use(struct dp_packet *b, void *base, size_t allocated)
      53                 :            : {
      54                 :      69902 :     dp_packet_use__(b, base, allocated, DPBUF_MALLOC);
      55                 :      69902 : }
      56                 :            : 
      57                 :            : /* Initializes 'b' as an empty dp_packet that contains the 'allocated' bytes of
      58                 :            :  * memory starting at 'base'.  'base' should point to a buffer on the stack.
      59                 :            :  * (Nothing actually relies on 'base' being allocated on the stack.  It could
      60                 :            :  * be static or malloc()'d memory.  But stack space is the most common use
      61                 :            :  * case.)
      62                 :            :  *
      63                 :            :  * 'base' should be appropriately aligned.  Using an array of uint32_t or
      64                 :            :  * uint64_t for the buffer is a reasonable way to ensure appropriate alignment
      65                 :            :  * for 32- or 64-bit data.
      66                 :            :  *
      67                 :            :  * An dp_packet operation that requires reallocating data will copy the provided
      68                 :            :  * buffer into a malloc()'d buffer.  Thus, it is wise to call dp_packet_uninit()
      69                 :            :  * on an dp_packet initialized by this function, so that if it expanded into the
      70                 :            :  * heap, that memory is freed. */
      71                 :            : void
      72                 :      16008 : dp_packet_use_stub(struct dp_packet *b, void *base, size_t allocated)
      73                 :            : {
      74                 :      16008 :     dp_packet_use__(b, base, allocated, DPBUF_STUB);
      75                 :      16008 : }
      76                 :            : 
      77                 :            : /* Initializes 'b' as an dp_packet whose data starts at 'data' and continues for
      78                 :            :  * 'size' bytes.  This is appropriate for an dp_packet that will be used to
      79                 :            :  * inspect existing data, without moving it around or reallocating it, and
      80                 :            :  * generally without modifying it at all.
      81                 :            :  *
      82                 :            :  * An dp_packet operation that requires reallocating data will assert-fail if this
      83                 :            :  * function was used to initialize it. */
      84                 :            : void
      85                 :      15007 : dp_packet_use_const(struct dp_packet *b, const void *data, size_t size)
      86                 :            : {
      87                 :      15007 :     dp_packet_use__(b, CONST_CAST(void *, data), size, DPBUF_STACK);
      88                 :      15007 :     dp_packet_set_size(b, size);
      89                 :      15007 : }
      90                 :            : 
      91                 :            : /* Initializes 'b' as an empty dp_packet that contains the 'allocated' bytes of
      92                 :            :  * memory starting at 'base'.  DPDK allocated dp_packet and *data is allocated
      93                 :            :  * from one continous memory region, so in memory data start right after
      94                 :            :  * dp_packet.  Therefore there is special method to free this type of
      95                 :            :  * buffer.  dp_packet base, data and size are initialized by dpdk rcv() so no
      96                 :            :  * need to initialize those fields. */
      97                 :            : void
      98                 :          0 : dp_packet_init_dpdk(struct dp_packet *b, size_t allocated)
      99                 :            : {
     100                 :          0 :     dp_packet_init__(b, allocated, DPBUF_DPDK);
     101                 :          0 : }
     102                 :            : 
     103                 :            : /* Initializes 'b' as an empty dp_packet with an initial capacity of 'size'
     104                 :            :  * bytes. */
     105                 :            : void
     106                 :      69902 : dp_packet_init(struct dp_packet *b, size_t size)
     107                 :            : {
     108         [ +  + ]:      69902 :     dp_packet_use(b, size ? xmalloc(size) : NULL, size);
     109                 :      69902 : }
     110                 :            : 
     111                 :            : /* Frees memory that 'b' points to. */
     112                 :            : void
     113                 :      85789 : dp_packet_uninit(struct dp_packet *b)
     114                 :            : {
     115         [ +  + ]:      85789 :     if (b) {
     116         [ +  + ]:      85788 :         if (b->source == DPBUF_MALLOC) {
     117                 :      70945 :             free(dp_packet_base(b));
     118                 :      14843 :         } else if (b->source == DPBUF_DPDK) {
     119                 :            : #ifdef DPDK_NETDEV
     120                 :            :             /* If this dp_packet was allocated by DPDK it must have been
     121                 :            :              * created as a dp_packet */
     122                 :            :             free_dpdk_buf((struct dp_packet*) b);
     123                 :            : #endif
     124                 :            :         }
     125                 :            :     }
     126                 :      85789 : }
     127                 :            : 
     128                 :            : /* Creates and returns a new dp_packet with an initial capacity of 'size'
     129                 :            :  * bytes. */
     130                 :            : struct dp_packet *
     131                 :      67647 : dp_packet_new(size_t size)
     132                 :            : {
     133                 :      67647 :     struct dp_packet *b = xmalloc(sizeof *b);
     134                 :      67647 :     dp_packet_init(b, size);
     135                 :      67647 :     return b;
     136                 :            : }
     137                 :            : 
     138                 :            : /* Creates and returns a new dp_packet with an initial capacity of 'size +
     139                 :            :  * headroom' bytes, reserving the first 'headroom' bytes as headroom. */
     140                 :            : struct dp_packet *
     141                 :      38066 : dp_packet_new_with_headroom(size_t size, size_t headroom)
     142                 :            : {
     143                 :      38066 :     struct dp_packet *b = dp_packet_new(size + headroom);
     144                 :      38066 :     dp_packet_reserve(b, headroom);
     145                 :      38066 :     return b;
     146                 :            : }
     147                 :            : 
     148                 :            : /* Creates and returns a new dp_packet that initially contains a copy of the
     149                 :            :  * 'dp_packet_size(buffer)' bytes of data starting at 'buffer->data' with no headroom or
     150                 :            :  * tailroom. */
     151                 :            : struct dp_packet *
     152                 :       6818 : dp_packet_clone(const struct dp_packet *buffer)
     153                 :            : {
     154                 :       6818 :     return dp_packet_clone_with_headroom(buffer, 0);
     155                 :            : }
     156                 :            : 
     157                 :            : /* Creates and returns a new dp_packet whose data are copied from 'buffer'.   The
     158                 :            :  * returned dp_packet will additionally have 'headroom' bytes of headroom. */
     159                 :            : struct dp_packet *
     160                 :       6818 : dp_packet_clone_with_headroom(const struct dp_packet *buffer, size_t headroom)
     161                 :            : {
     162                 :            :     struct dp_packet *new_buffer;
     163                 :            : 
     164                 :       6818 :     new_buffer = dp_packet_clone_data_with_headroom(dp_packet_data(buffer),
     165                 :       6818 :                                                  dp_packet_size(buffer),
     166                 :            :                                                  headroom);
     167                 :       6818 :     new_buffer->l2_pad_size = buffer->l2_pad_size;
     168                 :       6818 :     new_buffer->l2_5_ofs = buffer->l2_5_ofs;
     169                 :       6818 :     new_buffer->l3_ofs = buffer->l3_ofs;
     170                 :       6818 :     new_buffer->l4_ofs = buffer->l4_ofs;
     171                 :       6818 :     new_buffer->md = buffer->md;
     172                 :       6818 :     new_buffer->cutlen = buffer->cutlen;
     173                 :            : #ifdef DPDK_NETDEV
     174                 :            :     new_buffer->mbuf.ol_flags = buffer->mbuf.ol_flags;
     175                 :            : #else
     176                 :       6818 :     new_buffer->rss_hash_valid = buffer->rss_hash_valid;
     177                 :            : #endif
     178                 :            : 
     179         [ +  + ]:       6818 :     if (dp_packet_rss_valid(new_buffer)) {
     180                 :            : #ifdef DPDK_NETDEV
     181                 :            :         new_buffer->mbuf.hash.rss = buffer->mbuf.hash.rss;
     182                 :            : #else
     183                 :       1973 :         new_buffer->rss_hash = buffer->rss_hash;
     184                 :            : #endif
     185                 :            :     }
     186                 :            : 
     187                 :       6818 :     return new_buffer;
     188                 :            : }
     189                 :            : 
     190                 :            : /* Creates and returns a new dp_packet that initially contains a copy of the
     191                 :            :  * 'size' bytes of data starting at 'data' with no headroom or tailroom. */
     192                 :            : struct dp_packet *
     193                 :          0 : dp_packet_clone_data(const void *data, size_t size)
     194                 :            : {
     195                 :          0 :     return dp_packet_clone_data_with_headroom(data, size, 0);
     196                 :            : }
     197                 :            : 
     198                 :            : /* Creates and returns a new dp_packet that initially contains 'headroom' bytes of
     199                 :            :  * headroom followed by a copy of the 'size' bytes of data starting at
     200                 :            :  * 'data'. */
     201                 :            : struct dp_packet *
     202                 :      13102 : dp_packet_clone_data_with_headroom(const void *data, size_t size, size_t headroom)
     203                 :            : {
     204                 :      13102 :     struct dp_packet *b = dp_packet_new_with_headroom(size, headroom);
     205                 :      13102 :     dp_packet_put(b, data, size);
     206                 :      13102 :     return b;
     207                 :            : }
     208                 :            : 
     209                 :            : static void
     210                 :       3209 : dp_packet_copy__(struct dp_packet *b, uint8_t *new_base,
     211                 :            :               size_t new_headroom, size_t new_tailroom)
     212                 :            : {
     213                 :       3209 :     const uint8_t *old_base = dp_packet_base(b);
     214                 :       3209 :     size_t old_headroom = dp_packet_headroom(b);
     215                 :       3209 :     size_t old_tailroom = dp_packet_tailroom(b);
     216                 :       3209 :     size_t copy_headroom = MIN(old_headroom, new_headroom);
     217                 :       3209 :     size_t copy_tailroom = MIN(old_tailroom, new_tailroom);
     218                 :            : 
     219                 :       6418 :     memcpy(&new_base[new_headroom - copy_headroom],
     220                 :       3209 :            &old_base[old_headroom - copy_headroom],
     221                 :       3209 :            copy_headroom + dp_packet_size(b) + copy_tailroom);
     222                 :       3209 : }
     223                 :            : 
     224                 :            : /* Reallocates 'b' so that it has exactly 'new_headroom' and 'new_tailroom'
     225                 :            :  * bytes of headroom and tailroom, respectively. */
     226                 :            : static void
     227                 :       4804 : dp_packet_resize__(struct dp_packet *b, size_t new_headroom, size_t new_tailroom)
     228                 :            : {
     229                 :            :     void *new_base, *new_data;
     230                 :            :     size_t new_allocated;
     231                 :            : 
     232                 :       4804 :     new_allocated = new_headroom + dp_packet_size(b) + new_tailroom;
     233                 :            : 
     234   [ -  +  -  +  :       4804 :     switch (b->source) {
                      - ]
     235                 :            :     case DPBUF_DPDK:
     236                 :          0 :         OVS_NOT_REACHED();
     237                 :            : 
     238                 :            :     case DPBUF_MALLOC:
     239         [ +  + ]:       3686 :         if (new_headroom == dp_packet_headroom(b)) {
     240                 :       1595 :             new_base = xrealloc(dp_packet_base(b), new_allocated);
     241                 :            :         } else {
     242                 :       2091 :             new_base = xmalloc(new_allocated);
     243                 :       2091 :             dp_packet_copy__(b, new_base, new_headroom, new_tailroom);
     244                 :       2091 :             free(dp_packet_base(b));
     245                 :            :         }
     246                 :       3686 :         break;
     247                 :            : 
     248                 :            :     case DPBUF_STACK:
     249                 :          0 :         OVS_NOT_REACHED();
     250                 :            : 
     251                 :            :     case DPBUF_STUB:
     252                 :       1118 :         b->source = DPBUF_MALLOC;
     253                 :       1118 :         new_base = xmalloc(new_allocated);
     254                 :       1118 :         dp_packet_copy__(b, new_base, new_headroom, new_tailroom);
     255                 :       1118 :         break;
     256                 :            : 
     257                 :            :     default:
     258                 :          0 :         OVS_NOT_REACHED();
     259                 :            :     }
     260                 :            : 
     261                 :       4804 :     dp_packet_set_allocated(b, new_allocated);
     262                 :       4804 :     dp_packet_set_base(b, new_base);
     263                 :            : 
     264                 :       4804 :     new_data = (char *) new_base + new_headroom;
     265         [ +  + ]:       4804 :     if (dp_packet_data(b) != new_data) {
     266                 :       4550 :         dp_packet_set_data(b, new_data);
     267                 :            :     }
     268                 :       4804 : }
     269                 :            : 
     270                 :            : /* Ensures that 'b' has room for at least 'size' bytes at its tail end,
     271                 :            :  * reallocating and copying its data if necessary.  Its headroom, if any, is
     272                 :            :  * preserved. */
     273                 :            : void
     274                 :     424810 : dp_packet_prealloc_tailroom(struct dp_packet *b, size_t size)
     275                 :            : {
     276         [ +  + ]:     424810 :     if (size > dp_packet_tailroom(b)) {
     277                 :       1611 :         dp_packet_resize__(b, dp_packet_headroom(b), MAX(size, 64));
     278                 :            :     }
     279                 :     424810 : }
     280                 :            : 
     281                 :            : /* Ensures that 'b' has room for at least 'size' bytes at its head,
     282                 :            :  * reallocating and copying its data if necessary.  Its tailroom, if any, is
     283                 :            :  * preserved. */
     284                 :            : void
     285                 :      10378 : dp_packet_prealloc_headroom(struct dp_packet *b, size_t size)
     286                 :            : {
     287         [ +  + ]:      10378 :     if (size > dp_packet_headroom(b)) {
     288                 :       3193 :         dp_packet_resize__(b, MAX(size, 64), dp_packet_tailroom(b));
     289                 :            :     }
     290                 :      10378 : }
     291                 :            : 
     292                 :            : /* Shifts all of the data within the allocated space in 'b' by 'delta' bytes.
     293                 :            :  * For example, a 'delta' of 1 would cause each byte of data to move one byte
     294                 :            :  * forward (from address 'p' to 'p+1'), and a 'delta' of -1 would cause each
     295                 :            :  * byte to move one byte backward (from 'p' to 'p-1'). */
     296                 :            : void
     297                 :          0 : dp_packet_shift(struct dp_packet *b, int delta)
     298                 :            : {
     299 [ #  # ][ #  # ]:          0 :     ovs_assert(delta > 0 ? delta <= dp_packet_tailroom(b)
         [ #  # ][ #  # ]
     300                 :            :                : delta < 0 ? -delta <= dp_packet_headroom(b)
     301                 :            :                : true);
     302                 :            : 
     303         [ #  # ]:          0 :     if (delta != 0) {
     304                 :          0 :         char *dst = (char *) dp_packet_data(b) + delta;
     305                 :          0 :         memmove(dst, dp_packet_data(b), dp_packet_size(b));
     306                 :          0 :         dp_packet_set_data(b, dst);
     307                 :            :     }
     308                 :          0 : }
     309                 :            : 
     310                 :            : /* Appends 'size' bytes of data to the tail end of 'b', reallocating and
     311                 :            :  * copying its data if necessary.  Returns a pointer to the first byte of the
     312                 :            :  * new data, which is left uninitialized. */
     313                 :            : void *
     314                 :     295841 : dp_packet_put_uninit(struct dp_packet *b, size_t size)
     315                 :            : {
     316                 :            :     void *p;
     317                 :     295841 :     dp_packet_prealloc_tailroom(b, size);
     318                 :     295841 :     p = dp_packet_tail(b);
     319                 :     295841 :     dp_packet_set_size(b, dp_packet_size(b) + size);
     320                 :     295841 :     return p;
     321                 :            : }
     322                 :            : 
     323                 :            : /* Appends 'size' zeroed bytes to the tail end of 'b'.  Data in 'b' is
     324                 :            :  * reallocated and copied if necessary.  Returns a pointer to the first byte of
     325                 :            :  * the data's location in the dp_packet. */
     326                 :            : void *
     327                 :      80103 : dp_packet_put_zeros(struct dp_packet *b, size_t size)
     328                 :            : {
     329                 :      80103 :     void *dst = dp_packet_put_uninit(b, size);
     330                 :      80103 :     memset(dst, 0, size);
     331                 :      80103 :     return dst;
     332                 :            : }
     333                 :            : 
     334                 :            : /* Appends the 'size' bytes of data in 'p' to the tail end of 'b'.  Data in 'b'
     335                 :            :  * is reallocated and copied if necessary.  Returns a pointer to the first
     336                 :            :  * byte of the data's location in the dp_packet. */
     337                 :            : void *
     338                 :     195601 : dp_packet_put(struct dp_packet *b, const void *p, size_t size)
     339                 :            : {
     340                 :     195601 :     void *dst = dp_packet_put_uninit(b, size);
     341                 :     195601 :     memcpy(dst, p, size);
     342                 :     195601 :     return dst;
     343                 :            : }
     344                 :            : 
     345                 :            : /* Parses as many pairs of hex digits as possible (possibly separated by
     346                 :            :  * spaces) from the beginning of 's', appending bytes for their values to 'b'.
     347                 :            :  * Returns the first character of 's' that is not the first of a pair of hex
     348                 :            :  * digits.  If 'n' is nonnull, stores the number of bytes added to 'b' in
     349                 :            :  * '*n'. */
     350                 :            : char *
     351                 :       6051 : dp_packet_put_hex(struct dp_packet *b, const char *s, size_t *n)
     352                 :            : {
     353                 :       6051 :     size_t initial_size = dp_packet_size(b);
     354                 :            :     for (;;) {
     355                 :            :         uint8_t byte;
     356                 :            :         bool ok;
     357                 :            : 
     358                 :     161779 :         s += strspn(s, " \t\r\n");
     359                 :     161779 :         byte = hexits_value(s, 2, &ok);
     360         [ +  + ]:     161779 :         if (!ok) {
     361         [ -  + ]:       6051 :             if (n) {
     362                 :          0 :                 *n = dp_packet_size(b) - initial_size;
     363                 :            :             }
     364                 :       6051 :             return CONST_CAST(char *, s);
     365                 :            :         }
     366                 :            : 
     367                 :     155728 :         dp_packet_put(b, &byte, 1);
     368                 :     155728 :         s += 2;
     369                 :     155728 :     }
     370                 :            : }
     371                 :            : 
     372                 :            : /* Reserves 'size' bytes of headroom so that they can be later allocated with
     373                 :            :  * dp_packet_push_uninit() without reallocating the dp_packet. */
     374                 :            : void
     375                 :      60550 : dp_packet_reserve(struct dp_packet *b, size_t size)
     376                 :            : {
     377         [ -  + ]:      60550 :     ovs_assert(!dp_packet_size(b));
     378                 :      60550 :     dp_packet_prealloc_tailroom(b, size);
     379                 :      60550 :     dp_packet_set_data(b, (char*)dp_packet_data(b) + size);
     380                 :      60550 : }
     381                 :            : 
     382                 :            : /* Reserves 'headroom' bytes at the head and 'tailroom' at the end so that
     383                 :            :  * they can be later allocated with dp_packet_push_uninit() or
     384                 :            :  * dp_packet_put_uninit() without reallocating the dp_packet. */
     385                 :            : void
     386                 :          0 : dp_packet_reserve_with_tailroom(struct dp_packet *b, size_t headroom,
     387                 :            :                              size_t tailroom)
     388                 :            : {
     389         [ #  # ]:          0 :     ovs_assert(!dp_packet_size(b));
     390                 :          0 :     dp_packet_prealloc_tailroom(b, headroom + tailroom);
     391                 :          0 :     dp_packet_set_data(b, (char*)dp_packet_data(b) + headroom);
     392                 :          0 : }
     393                 :            : 
     394                 :            : /* Prefixes 'size' bytes to the head end of 'b', reallocating and copying its
     395                 :            :  * data if necessary.  Returns a pointer to the first byte of the data's
     396                 :            :  * location in the dp_packet.  The new data is left uninitialized. */
     397                 :            : void *
     398                 :      10378 : dp_packet_push_uninit(struct dp_packet *b, size_t size)
     399                 :            : {
     400                 :      10378 :     dp_packet_prealloc_headroom(b, size);
     401                 :      10378 :     dp_packet_set_data(b, (char*)dp_packet_data(b) - size);
     402                 :      10378 :     dp_packet_set_size(b, dp_packet_size(b) + size);
     403                 :      10378 :     return dp_packet_data(b);
     404                 :            : }
     405                 :            : 
     406                 :            : /* Prefixes 'size' zeroed bytes to the head end of 'b', reallocating and
     407                 :            :  * copying its data if necessary.  Returns a pointer to the first byte of the
     408                 :            :  * data's location in the dp_packet. */
     409                 :            : void *
     410                 :          0 : dp_packet_push_zeros(struct dp_packet *b, size_t size)
     411                 :            : {
     412                 :          0 :     void *dst = dp_packet_push_uninit(b, size);
     413                 :          0 :     memset(dst, 0, size);
     414                 :          0 :     return dst;
     415                 :            : }
     416                 :            : 
     417                 :            : /* Copies the 'size' bytes starting at 'p' to the head end of 'b', reallocating
     418                 :            :  * and copying its data if necessary.  Returns a pointer to the first byte of
     419                 :            :  * the data's location in the dp_packet. */
     420                 :            : void *
     421                 :          0 : dp_packet_push(struct dp_packet *b, const void *p, size_t size)
     422                 :            : {
     423                 :          0 :     void *dst = dp_packet_push_uninit(b, size);
     424                 :          0 :     memcpy(dst, p, size);
     425                 :          0 :     return dst;
     426                 :            : }
     427                 :            : 
     428                 :            : /* Returns the data in 'b' as a block of malloc()'d memory and frees the buffer
     429                 :            :  * within 'b'.  (If 'b' itself was dynamically allocated, e.g. with
     430                 :            :  * dp_packet_new(), then it should still be freed with, e.g., dp_packet_delete().) */
     431                 :            : void *
     432                 :        857 : dp_packet_steal_data(struct dp_packet *b)
     433                 :            : {
     434                 :            :     void *p;
     435         [ -  + ]:        857 :     ovs_assert(b->source != DPBUF_DPDK);
     436                 :            : 
     437 [ +  - ][ +  + ]:        857 :     if (b->source == DPBUF_MALLOC && dp_packet_data(b) == dp_packet_base(b)) {
     438                 :        724 :         p = dp_packet_data(b);
     439                 :            :     } else {
     440                 :        133 :         p = xmemdup(dp_packet_data(b), dp_packet_size(b));
     441         [ +  - ]:        133 :         if (b->source == DPBUF_MALLOC) {
     442                 :        133 :             free(dp_packet_base(b));
     443                 :            :         }
     444                 :            :     }
     445                 :        857 :     dp_packet_set_base(b, NULL);
     446                 :        857 :     dp_packet_set_data(b, NULL);
     447                 :        857 :     return p;
     448                 :            : }
     449                 :            : 
     450                 :            : static inline void
     451                 :       8094 : dp_packet_adjust_layer_offset(uint16_t *offset, int increment)
     452                 :            : {
     453         [ +  + ]:       8094 :     if (*offset != UINT16_MAX) {
     454                 :       4107 :         *offset += increment;
     455                 :            :     }
     456                 :       8094 : }
     457                 :            : 
     458                 :            : /* Adjust the size of the l2_5 portion of the dp_packet, updating the l2
     459                 :            :  * pointer and the layer offsets.  The caller is responsible for
     460                 :            :  * modifying the contents. */
     461                 :            : void *
     462                 :       3904 : dp_packet_resize_l2_5(struct dp_packet *b, int increment)
     463                 :            : {
     464         [ +  + ]:       3904 :     if (increment >= 0) {
     465                 :       3729 :         dp_packet_push_uninit(b, increment);
     466                 :            :     } else {
     467                 :        175 :         dp_packet_pull(b, -increment);
     468                 :            :     }
     469                 :            : 
     470                 :            :     /* Adjust layer offsets after l2_5. */
     471                 :       3904 :     dp_packet_adjust_layer_offset(&b->l3_ofs, increment);
     472                 :       3904 :     dp_packet_adjust_layer_offset(&b->l4_ofs, increment);
     473                 :            : 
     474                 :       3904 :     return dp_packet_data(b);
     475                 :            : }
     476                 :            : 
     477                 :            : /* Adjust the size of the l2 portion of the dp_packet, updating the l2
     478                 :            :  * pointer and the layer offsets.  The caller is responsible for
     479                 :            :  * modifying the contents. */
     480                 :            : void *
     481                 :        286 : dp_packet_resize_l2(struct dp_packet *b, int increment)
     482                 :            : {
     483                 :        286 :     dp_packet_resize_l2_5(b, increment);
     484                 :        286 :     dp_packet_adjust_layer_offset(&b->l2_5_ofs, increment);
     485                 :        286 :     return dp_packet_data(b);
     486                 :            : }

Generated by: LCOV version 1.12