LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - network_spgist.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 43.6 % 307 134 7 91 75 5 67 62 93 65
Current Date: 2023-04-08 15:15:32 Functions: 42.9 % 7 3 4 3 4 3
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * network_spgist.c
       4                 :  *    SP-GiST support for network types.
       5                 :  *
       6                 :  * We split inet index entries first by address family (IPv4 or IPv6).
       7                 :  * If the entries below a given inner tuple are all of the same family,
       8                 :  * we identify their common prefix and split by the next bit of the address,
       9                 :  * and by whether their masklens exceed the length of the common prefix.
      10                 :  *
      11                 :  * An inner tuple that has both IPv4 and IPv6 children has a null prefix
      12                 :  * and exactly two nodes, the first being for IPv4 and the second for IPv6.
      13                 :  *
      14                 :  * Otherwise, the prefix is a CIDR value representing the common prefix,
      15                 :  * and there are exactly four nodes.  Node numbers 0 and 1 are for addresses
      16                 :  * with the same masklen as the prefix, while node numbers 2 and 3 are for
      17                 :  * addresses with larger masklen.  (We do not allow a tuple to contain
      18                 :  * entries with masklen smaller than its prefix's.)  Node numbers 0 and 1
      19                 :  * are distinguished by the next bit of the address after the common prefix,
      20                 :  * and likewise for node numbers 2 and 3.  If there are no more bits in
      21                 :  * the address family, everything goes into node 0 (which will probably
      22                 :  * lead to creating an allTheSame tuple).
      23                 :  *
      24                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      25                 :  * Portions Copyright (c) 1994, Regents of the University of California
      26                 :  *
      27                 :  * IDENTIFICATION
      28                 :  *          src/backend/utils/adt/network_spgist.c
      29                 :  *
      30                 :  *-------------------------------------------------------------------------
      31                 :  */
      32                 : #include "postgres.h"
      33                 : 
      34                 : #include <sys/socket.h>
      35                 : 
      36                 : #include "access/spgist.h"
      37                 : #include "catalog/pg_type.h"
      38                 : #include "utils/builtins.h"
      39                 : #include "utils/inet.h"
      40                 : #include "varatt.h"
      41                 : 
      42                 : 
      43                 : static int  inet_spg_node_number(const inet *val, int commonbits);
      44                 : static int  inet_spg_consistent_bitmap(const inet *prefix, int nkeys,
      45                 :                                        ScanKey scankeys, bool leaf);
      46                 : 
      47                 : /*
      48                 :  * The SP-GiST configuration function
      49                 :  */
      50                 : Datum
      51 GIC           9 : inet_spg_config(PG_FUNCTION_ARGS)
      52 ECB             : {
      53                 :     /* spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0); */
      54 GIC           9 :     spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1);
      55 ECB             : 
      56 GIC           9 :     cfg->prefixType = CIDROID;
      57 CBC           9 :     cfg->labelType = VOIDOID;
      58               9 :     cfg->canReturnData = true;
      59               9 :     cfg->longValuesOK = false;
      60 ECB             : 
      61 GIC           9 :     PG_RETURN_VOID();
      62 ECB             : }
      63                 : 
      64                 : /*
      65                 :  * The SP-GiST choose function
      66                 :  */
      67                 : Datum
      68 UIC           0 : inet_spg_choose(PG_FUNCTION_ARGS)
      69 EUB             : {
      70 UIC           0 :     spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
      71 UBC           0 :     spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
      72               0 :     inet       *val = DatumGetInetPP(in->datum),
      73 EUB             :                *prefix;
      74                 :     int         commonbits;
      75                 : 
      76                 :     /*
      77                 :      * If we're looking at a tuple that splits by address family, choose the
      78                 :      * appropriate subnode.
      79                 :      */
      80 UIC           0 :     if (!in->hasPrefix)
      81 EUB             :     {
      82                 :         /* allTheSame isn't possible for such a tuple */
      83 UIC           0 :         Assert(!in->allTheSame);
      84 UBC           0 :         Assert(in->nNodes == 2);
      85 EUB             : 
      86 UIC           0 :         out->resultType = spgMatchNode;
      87 UBC           0 :         out->result.matchNode.nodeN = (ip_family(val) == PGSQL_AF_INET) ? 0 : 1;
      88               0 :         out->result.matchNode.restDatum = InetPGetDatum(val);
      89 EUB             : 
      90 UIC           0 :         PG_RETURN_VOID();
      91 EUB             :     }
      92                 : 
      93                 :     /* Else it must split by prefix */
      94 UIC           0 :     Assert(in->nNodes == 4 || in->allTheSame);
      95 EUB             : 
      96 UIC           0 :     prefix = DatumGetInetPP(in->prefixDatum);
      97 UBC           0 :     commonbits = ip_bits(prefix);
      98 EUB             : 
      99                 :     /*
     100                 :      * We cannot put addresses from different families under the same inner
     101                 :      * node, so we have to split if the new value's family is different.
     102                 :      */
     103 UIC           0 :     if (ip_family(val) != ip_family(prefix))
     104 EUB             :     {
     105                 :         /* Set up 2-node tuple */
     106 UIC           0 :         out->resultType = spgSplitTuple;
     107 UBC           0 :         out->result.splitTuple.prefixHasPrefix = false;
     108               0 :         out->result.splitTuple.prefixNNodes = 2;
     109               0 :         out->result.splitTuple.prefixNodeLabels = NULL;
     110 EUB             : 
     111                 :         /* Identify which node the existing data goes into */
     112 UIC           0 :         out->result.splitTuple.childNodeN =
     113 UBC           0 :             (ip_family(prefix) == PGSQL_AF_INET) ? 0 : 1;
     114 EUB             : 
     115 UIC           0 :         out->result.splitTuple.postfixHasPrefix = true;
     116 UBC           0 :         out->result.splitTuple.postfixPrefixDatum = InetPGetDatum(prefix);
     117 EUB             : 
     118 UIC           0 :         PG_RETURN_VOID();
     119 EUB             :     }
     120                 : 
     121                 :     /*
     122                 :      * If the new value does not match the existing prefix, we have to split.
     123                 :      */
     124 UIC           0 :     if (ip_bits(val) < commonbits ||
     125 UBC           0 :         bitncmp(ip_addr(prefix), ip_addr(val), commonbits) != 0)
     126 EUB             :     {
     127                 :         /* Determine new prefix length for the split tuple */
     128 UIC           0 :         commonbits = bitncommon(ip_addr(prefix), ip_addr(val),
     129 UBC           0 :                                 Min(ip_bits(val), commonbits));
     130 EUB             : 
     131                 :         /* Set up 4-node tuple */
     132 UIC           0 :         out->resultType = spgSplitTuple;
     133 UBC           0 :         out->result.splitTuple.prefixHasPrefix = true;
     134               0 :         out->result.splitTuple.prefixPrefixDatum =
     135               0 :             InetPGetDatum(cidr_set_masklen_internal(val, commonbits));
     136               0 :         out->result.splitTuple.prefixNNodes = 4;
     137               0 :         out->result.splitTuple.prefixNodeLabels = NULL;
     138 EUB             : 
     139                 :         /* Identify which node the existing data goes into */
     140 UIC           0 :         out->result.splitTuple.childNodeN =
     141 UBC           0 :             inet_spg_node_number(prefix, commonbits);
     142 EUB             : 
     143 UIC           0 :         out->result.splitTuple.postfixHasPrefix = true;
     144 UBC           0 :         out->result.splitTuple.postfixPrefixDatum = InetPGetDatum(prefix);
     145 EUB             : 
     146 UIC           0 :         PG_RETURN_VOID();
     147 EUB             :     }
     148                 : 
     149                 :     /*
     150                 :      * All OK, choose the node to descend into.  (If this tuple is marked
     151                 :      * allTheSame, the core code will ignore our choice of nodeN; but we need
     152                 :      * not account for that case explicitly here.)
     153                 :      */
     154 UIC           0 :     out->resultType = spgMatchNode;
     155 UBC           0 :     out->result.matchNode.nodeN = inet_spg_node_number(val, commonbits);
     156               0 :     out->result.matchNode.restDatum = InetPGetDatum(val);
     157 EUB             : 
     158 UIC           0 :     PG_RETURN_VOID();
     159 EUB             : }
     160                 : 
     161                 : /*
     162                 :  * The GiST PickSplit method
     163                 :  */
     164                 : Datum
     165 UIC           0 : inet_spg_picksplit(PG_FUNCTION_ARGS)
     166 EUB             : {
     167 UIC           0 :     spgPickSplitIn *in = (spgPickSplitIn *) PG_GETARG_POINTER(0);
     168 UBC           0 :     spgPickSplitOut *out = (spgPickSplitOut *) PG_GETARG_POINTER(1);
     169 EUB             :     inet       *prefix,
     170                 :                *tmp;
     171                 :     int         i,
     172                 :                 commonbits;
     173 UIC           0 :     bool        differentFamilies = false;
     174 EUB             : 
     175                 :     /* Initialize the prefix with the first item */
     176 UIC           0 :     prefix = DatumGetInetPP(in->datums[0]);
     177 UBC           0 :     commonbits = ip_bits(prefix);
     178 EUB             : 
     179                 :     /* Examine remaining items to discover minimum common prefix length */
     180 UIC           0 :     for (i = 1; i < in->nTuples; i++)
     181 EUB             :     {
     182 UIC           0 :         tmp = DatumGetInetPP(in->datums[i]);
     183 EUB             : 
     184 UIC           0 :         if (ip_family(tmp) != ip_family(prefix))
     185 EUB             :         {
     186 UIC           0 :             differentFamilies = true;
     187 UBC           0 :             break;
     188 EUB             :         }
     189                 : 
     190 UIC           0 :         if (ip_bits(tmp) < commonbits)
     191 UBC           0 :             commonbits = ip_bits(tmp);
     192               0 :         commonbits = bitncommon(ip_addr(prefix), ip_addr(tmp), commonbits);
     193               0 :         if (commonbits == 0)
     194               0 :             break;
     195 EUB             :     }
     196                 : 
     197                 :     /* Don't need labels; allocate output arrays */
     198 UIC           0 :     out->nodeLabels = NULL;
     199 UBC           0 :     out->mapTuplesToNodes = (int *) palloc(sizeof(int) * in->nTuples);
     200               0 :     out->leafTupleDatums = (Datum *) palloc(sizeof(Datum) * in->nTuples);
     201 EUB             : 
     202 UIC           0 :     if (differentFamilies)
     203 EUB             :     {
     204                 :         /* Set up 2-node tuple */
     205 UIC           0 :         out->hasPrefix = false;
     206 UBC           0 :         out->nNodes = 2;
     207 EUB             : 
     208 UIC           0 :         for (i = 0; i < in->nTuples; i++)
     209 EUB             :         {
     210 UIC           0 :             tmp = DatumGetInetPP(in->datums[i]);
     211 UBC           0 :             out->mapTuplesToNodes[i] =
     212               0 :                 (ip_family(tmp) == PGSQL_AF_INET) ? 0 : 1;
     213               0 :             out->leafTupleDatums[i] = InetPGetDatum(tmp);
     214 EUB             :         }
     215                 :     }
     216                 :     else
     217                 :     {
     218                 :         /* Set up 4-node tuple */
     219 UIC           0 :         out->hasPrefix = true;
     220 UBC           0 :         out->prefixDatum =
     221               0 :             InetPGetDatum(cidr_set_masklen_internal(prefix, commonbits));
     222               0 :         out->nNodes = 4;
     223 EUB             : 
     224 UIC           0 :         for (i = 0; i < in->nTuples; i++)
     225 EUB             :         {
     226 UIC           0 :             tmp = DatumGetInetPP(in->datums[i]);
     227 UBC           0 :             out->mapTuplesToNodes[i] = inet_spg_node_number(tmp, commonbits);
     228               0 :             out->leafTupleDatums[i] = InetPGetDatum(tmp);
     229 EUB             :         }
     230                 :     }
     231                 : 
     232 UIC           0 :     PG_RETURN_VOID();
     233 EUB             : }
     234                 : 
     235                 : /*
     236                 :  * The SP-GiST query consistency check for inner tuples
     237                 :  */
     238                 : Datum
     239 UIC           0 : inet_spg_inner_consistent(PG_FUNCTION_ARGS)
     240 EUB             : {
     241 UIC           0 :     spgInnerConsistentIn *in = (spgInnerConsistentIn *) PG_GETARG_POINTER(0);
     242 UBC           0 :     spgInnerConsistentOut *out = (spgInnerConsistentOut *) PG_GETARG_POINTER(1);
     243 EUB             :     int         i;
     244                 :     int         which;
     245                 : 
     246 UIC           0 :     if (!in->hasPrefix)
     247 EUB             :     {
     248 UIC           0 :         Assert(!in->allTheSame);
     249 UBC           0 :         Assert(in->nNodes == 2);
     250 EUB             : 
     251                 :         /* Identify which child nodes need to be visited */
     252 UIC           0 :         which = 1 | (1 << 1);
     253 EUB             : 
     254 UIC           0 :         for (i = 0; i < in->nkeys; i++)
     255 EUB             :         {
     256 UIC           0 :             StrategyNumber strategy = in->scankeys[i].sk_strategy;
     257 UBC           0 :             inet       *argument = DatumGetInetPP(in->scankeys[i].sk_argument);
     258 EUB             : 
     259 UIC           0 :             switch (strategy)
     260 EUB             :             {
     261 UIC           0 :                 case RTLessStrategyNumber:
     262 EUB             :                 case RTLessEqualStrategyNumber:
     263 UIC           0 :                     if (ip_family(argument) == PGSQL_AF_INET)
     264 UBC           0 :                         which &= 1;
     265               0 :                     break;
     266 EUB             : 
     267 UIC           0 :                 case RTGreaterEqualStrategyNumber:
     268 EUB             :                 case RTGreaterStrategyNumber:
     269 UIC           0 :                     if (ip_family(argument) == PGSQL_AF_INET6)
     270 UBC           0 :                         which &= (1 << 1);
     271               0 :                     break;
     272 EUB             : 
     273 UIC           0 :                 case RTNotEqualStrategyNumber:
     274 UBC           0 :                     break;
     275 EUB             : 
     276 UIC           0 :                 default:
     277 EUB             :                     /* all other ops can only match addrs of same family */
     278 UIC           0 :                     if (ip_family(argument) == PGSQL_AF_INET)
     279 UBC           0 :                         which &= 1;
     280 EUB             :                     else
     281 UIC           0 :                         which &= (1 << 1);
     282 UBC           0 :                     break;
     283 EUB             :             }
     284                 :         }
     285                 :     }
     286 UIC           0 :     else if (!in->allTheSame)
     287 EUB             :     {
     288 UIC           0 :         Assert(in->nNodes == 4);
     289 EUB             : 
     290                 :         /* Identify which child nodes need to be visited */
     291 UIC           0 :         which = inet_spg_consistent_bitmap(DatumGetInetPP(in->prefixDatum),
     292 EUB             :                                            in->nkeys, in->scankeys, false);
     293                 :     }
     294                 :     else
     295                 :     {
     296                 :         /* Must visit all nodes; we assume there are less than 32 of 'em */
     297 UIC           0 :         which = ~0;
     298 EUB             :     }
     299                 : 
     300 UIC           0 :     out->nNodes = 0;
     301 EUB             : 
     302 UIC           0 :     if (which)
     303 EUB             :     {
     304 UIC           0 :         out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes);
     305 EUB             : 
     306 UIC           0 :         for (i = 0; i < in->nNodes; i++)
     307 EUB             :         {
     308 UIC           0 :             if (which & (1 << i))
     309 EUB             :             {
     310 UIC           0 :                 out->nodeNumbers[out->nNodes] = i;
     311 UBC           0 :                 out->nNodes++;
     312 EUB             :             }
     313                 :         }
     314                 :     }
     315                 : 
     316 UIC           0 :     PG_RETURN_VOID();
     317 EUB             : }
     318                 : 
     319                 : /*
     320                 :  * The SP-GiST query consistency check for leaf tuples
     321                 :  */
     322                 : Datum
     323 GIC         612 : inet_spg_leaf_consistent(PG_FUNCTION_ARGS)
     324 ECB             : {
     325 GIC         612 :     spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0);
     326 CBC         612 :     spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1);
     327             612 :     inet       *leaf = DatumGetInetPP(in->leafDatum);
     328 ECB             : 
     329                 :     /* All tests are exact. */
     330 GIC         612 :     out->recheck = false;
     331 ECB             : 
     332                 :     /* Leaf is what it is... */
     333 GIC         612 :     out->leafValue = InetPGetDatum(leaf);
     334 ECB             : 
     335                 :     /* Use common code to apply the tests. */
     336 GIC         612 :     PG_RETURN_BOOL(inet_spg_consistent_bitmap(leaf, in->nkeys, in->scankeys,
     337 ECB             :                                               true));
     338                 : }
     339                 : 
     340                 : /*
     341                 :  * Calculate node number (within a 4-node, single-family inner index tuple)
     342                 :  *
     343                 :  * The value must have the same family as the node's prefix, and
     344                 :  * commonbits is the mask length of the prefix.  We use even or odd
     345                 :  * nodes according to the next address bit after the commonbits,
     346                 :  * and low or high nodes according to whether the value's mask length
     347                 :  * is larger than commonbits.
     348                 :  */
     349                 : static int
     350 UIC           0 : inet_spg_node_number(const inet *val, int commonbits)
     351 EUB             : {
     352 UIC           0 :     int         nodeN = 0;
     353 EUB             : 
     354 UIC           0 :     if (commonbits < ip_maxbits(val) &&
     355 UBC           0 :         ip_addr(val)[commonbits / 8] & (1 << (7 - commonbits % 8)))
     356               0 :         nodeN |= 1;
     357               0 :     if (commonbits < ip_bits(val))
     358               0 :         nodeN |= 2;
     359 EUB             : 
     360 UIC           0 :     return nodeN;
     361 EUB             : }
     362                 : 
     363                 : /*
     364                 :  * Calculate bitmap of node numbers that are consistent with the query
     365                 :  *
     366                 :  * This can be used either at a 4-way inner tuple, or at a leaf tuple.
     367                 :  * In the latter case, we should return a boolean result (0 or 1)
     368                 :  * not a bitmap.
     369                 :  *
     370                 :  * This definition is pretty odd, but the inner and leaf consistency checks
     371                 :  * are mostly common and it seems best to keep them in one function.
     372                 :  */
     373                 : static int
     374 GIC         612 : inet_spg_consistent_bitmap(const inet *prefix, int nkeys, ScanKey scankeys,
     375 ECB             :                            bool leaf)
     376                 : {
     377                 :     int         bitmap;
     378                 :     int         commonbits,
     379                 :                 i;
     380                 : 
     381                 :     /* Initialize result to allow visiting all children */
     382 GIC         612 :     if (leaf)
     383 CBC         612 :         bitmap = 1;
     384 ECB             :     else
     385 UIC           0 :         bitmap = 1 | (1 << 1) | (1 << 2) | (1 << 3);
     386 EUB             : 
     387 GIC         612 :     commonbits = ip_bits(prefix);
     388 ECB             : 
     389 GIC         828 :     for (i = 0; i < nkeys; i++)
     390 ECB             :     {
     391 GIC         612 :         inet       *argument = DatumGetInetPP(scankeys[i].sk_argument);
     392 CBC         612 :         StrategyNumber strategy = scankeys[i].sk_strategy;
     393 ECB             :         int         order;
     394                 : 
     395                 :         /*
     396                 :          * Check 0: different families
     397                 :          *
     398                 :          * Matching families do not help any of the strategies.
     399                 :          */
     400 GIC         612 :         if (ip_family(argument) != ip_family(prefix))
     401 ECB             :         {
     402 GIC         108 :             switch (strategy)
     403 ECB             :             {
     404 GIC          18 :                 case RTLessStrategyNumber:
     405 ECB             :                 case RTLessEqualStrategyNumber:
     406 GIC          18 :                     if (ip_family(argument) < ip_family(prefix))
     407 CBC          18 :                         bitmap = 0;
     408              18 :                     break;
     409 ECB             : 
     410 GIC          18 :                 case RTGreaterEqualStrategyNumber:
     411 ECB             :                 case RTGreaterStrategyNumber:
     412 GIC          18 :                     if (ip_family(argument) > ip_family(prefix))
     413 LBC           0 :                         bitmap = 0;
     414 GBC          18 :                     break;
     415 ECB             : 
     416 GIC           9 :                 case RTNotEqualStrategyNumber:
     417 CBC           9 :                     break;
     418 ECB             : 
     419 GIC          63 :                 default:
     420 ECB             :                     /* For all other cases, we can be sure there is no match */
     421 GIC          63 :                     bitmap = 0;
     422 CBC          63 :                     break;
     423 ECB             :             }
     424                 : 
     425 GIC         108 :             if (!bitmap)
     426 CBC          81 :                 break;
     427 ECB             : 
     428                 :             /* Other checks make no sense with different families. */
     429 GIC          27 :             continue;
     430 ECB             :         }
     431                 : 
     432                 :         /*
     433                 :          * Check 1: network bit count
     434                 :          *
     435                 :          * Network bit count (ip_bits) helps to check leaves for sub network
     436                 :          * and sup network operators.  At non-leaf nodes, we know every child
     437                 :          * value has greater ip_bits, so we can avoid descending in some cases
     438                 :          * too.
     439                 :          *
     440                 :          * This check is less expensive than checking the address bits, so we
     441                 :          * are doing this before, but it has to be done after for the basic
     442                 :          * comparison strategies, because ip_bits only affect their results
     443                 :          * when the common network bits are the same.
     444                 :          */
     445 GIC         504 :         switch (strategy)
     446 ECB             :         {
     447 GIC          84 :             case RTSubStrategyNumber:
     448 CBC          84 :                 if (commonbits <= ip_bits(argument))
     449              60 :                     bitmap &= (1 << 2) | (1 << 3);
     450              84 :                 break;
     451 ECB             : 
     452 GIC          42 :             case RTSubEqualStrategyNumber:
     453 CBC          42 :                 if (commonbits < ip_bits(argument))
     454              18 :                     bitmap &= (1 << 2) | (1 << 3);
     455              42 :                 break;
     456 ECB             : 
     457 GIC          42 :             case RTSuperStrategyNumber:
     458 CBC          42 :                 if (commonbits == ip_bits(argument) - 1)
     459 LBC           0 :                     bitmap &= 1 | (1 << 1);
     460 GBC          42 :                 else if (commonbits >= ip_bits(argument))
     461 CBC          24 :                     bitmap = 0;
     462              42 :                 break;
     463 ECB             : 
     464 GIC          42 :             case RTSuperEqualStrategyNumber:
     465 CBC          42 :                 if (commonbits == ip_bits(argument))
     466              12 :                     bitmap &= 1 | (1 << 1);
     467              30 :                 else if (commonbits > ip_bits(argument))
     468              12 :                     bitmap = 0;
     469              42 :                 break;
     470 ECB             : 
     471 GIC          42 :             case RTEqualStrategyNumber:
     472 CBC          42 :                 if (commonbits < ip_bits(argument))
     473              18 :                     bitmap &= (1 << 2) | (1 << 3);
     474              24 :                 else if (commonbits == ip_bits(argument))
     475              12 :                     bitmap &= 1 | (1 << 1);
     476 ECB             :                 else
     477 GIC          12 :                     bitmap = 0;
     478 CBC          42 :                 break;
     479 ECB             :         }
     480                 : 
     481 GIC         504 :         if (!bitmap)
     482 CBC         144 :             break;
     483 ECB             : 
     484                 :         /*
     485                 :          * Check 2: common network bits
     486                 :          *
     487                 :          * Compare available common prefix bits to the query, but not beyond
     488                 :          * either the query's netmask or the minimum netmask among the
     489                 :          * represented values.  If these bits don't match the query, we can
     490                 :          * eliminate some cases.
     491                 :          */
     492 GIC         360 :         order = bitncmp(ip_addr(prefix), ip_addr(argument),
     493 CBC         360 :                         Min(commonbits, ip_bits(argument)));
     494 ECB             : 
     495 GIC         360 :         if (order != 0)
     496 ECB             :         {
     497 GIC         198 :             switch (strategy)
     498 ECB             :             {
     499 GIC          48 :                 case RTLessStrategyNumber:
     500 ECB             :                 case RTLessEqualStrategyNumber:
     501 GIC          48 :                     if (order > 0)
     502 LBC           0 :                         bitmap = 0;
     503 GBC          48 :                     break;
     504 ECB             : 
     505 GIC          48 :                 case RTGreaterEqualStrategyNumber:
     506 ECB             :                 case RTGreaterStrategyNumber:
     507 GIC          48 :                     if (order < 0)
     508 CBC          48 :                         bitmap = 0;
     509              48 :                     break;
     510 ECB             : 
     511 GIC          24 :                 case RTNotEqualStrategyNumber:
     512 CBC          24 :                     break;
     513 ECB             : 
     514 GIC          78 :                 default:
     515 ECB             :                     /* For all other cases, we can be sure there is no match */
     516 GIC          78 :                     bitmap = 0;
     517 CBC          78 :                     break;
     518 ECB             :             }
     519                 : 
     520 GIC         198 :             if (!bitmap)
     521 CBC         126 :                 break;
     522 ECB             : 
     523                 :             /*
     524                 :              * Remaining checks make no sense when common bits don't match.
     525                 :              */
     526 GIC          72 :             continue;
     527 ECB             :         }
     528                 : 
     529                 :         /*
     530                 :          * Check 3: next network bit
     531                 :          *
     532                 :          * We can filter out branch 2 or 3 using the next network bit of the
     533                 :          * argument, if it is available.
     534                 :          *
     535                 :          * This check matters for the performance of the search. The results
     536                 :          * would be correct without it.
     537                 :          */
     538 GIC         162 :         if (bitmap & ((1 << 2) | (1 << 3)) &&
     539 LBC           0 :             commonbits < ip_bits(argument))
     540 EUB             :         {
     541                 :             int         nextbit;
     542                 : 
     543 UIC           0 :             nextbit = ip_addr(argument)[commonbits / 8] &
     544 UBC           0 :                 (1 << (7 - commonbits % 8));
     545 EUB             : 
     546 UIC           0 :             switch (strategy)
     547 EUB             :             {
     548 UIC           0 :                 case RTLessStrategyNumber:
     549 EUB             :                 case RTLessEqualStrategyNumber:
     550 UIC           0 :                     if (!nextbit)
     551 UBC           0 :                         bitmap &= 1 | (1 << 1) | (1 << 2);
     552               0 :                     break;
     553 EUB             : 
     554 UIC           0 :                 case RTGreaterEqualStrategyNumber:
     555 EUB             :                 case RTGreaterStrategyNumber:
     556 UIC           0 :                     if (nextbit)
     557 UBC           0 :                         bitmap &= 1 | (1 << 1) | (1 << 3);
     558               0 :                     break;
     559 EUB             : 
     560 UIC           0 :                 case RTNotEqualStrategyNumber:
     561 UBC           0 :                     break;
     562 EUB             : 
     563 UIC           0 :                 default:
     564 UBC           0 :                     if (!nextbit)
     565               0 :                         bitmap &= 1 | (1 << 1) | (1 << 2);
     566 EUB             :                     else
     567 UIC           0 :                         bitmap &= 1 | (1 << 1) | (1 << 3);
     568 UBC           0 :                     break;
     569 EUB             :             }
     570                 : 
     571 UIC           0 :             if (!bitmap)
     572 UBC           0 :                 break;
     573 EUB             :         }
     574                 : 
     575                 :         /*
     576                 :          * Remaining checks are only for the basic comparison strategies. This
     577                 :          * test relies on the strategy number ordering defined in stratnum.h.
     578                 :          */
     579 GIC         162 :         if (strategy < RTEqualStrategyNumber ||
     580 ECB             :             strategy > RTGreaterEqualStrategyNumber)
     581 GIC          63 :             continue;
     582 ECB             : 
     583                 :         /*
     584                 :          * Check 4: network bit count
     585                 :          *
     586                 :          * At this point, we know that the common network bits of the prefix
     587                 :          * and the argument are the same, so we can go forward and check the
     588                 :          * ip_bits.
     589                 :          */
     590 GIC          99 :         switch (strategy)
     591 ECB             :         {
     592 GIC          36 :             case RTLessStrategyNumber:
     593 ECB             :             case RTLessEqualStrategyNumber:
     594 GIC          36 :                 if (commonbits == ip_bits(argument))
     595 CBC          18 :                     bitmap &= 1 | (1 << 1);
     596              18 :                 else if (commonbits > ip_bits(argument))
     597              18 :                     bitmap = 0;
     598              36 :                 break;
     599 ECB             : 
     600 GIC          36 :             case RTGreaterEqualStrategyNumber:
     601 ECB             :             case RTGreaterStrategyNumber:
     602 GIC          36 :                 if (commonbits < ip_bits(argument))
     603 LBC           0 :                     bitmap &= (1 << 2) | (1 << 3);
     604 GBC          36 :                 break;
     605 ECB             :         }
     606                 : 
     607 GIC          99 :         if (!bitmap)
     608 CBC          18 :             break;
     609 ECB             : 
     610                 :         /* Remaining checks don't make sense with different ip_bits. */
     611 GIC          81 :         if (commonbits != ip_bits(argument))
     612 CBC          27 :             continue;
     613 ECB             : 
     614                 :         /*
     615                 :          * Check 5: next host bit
     616                 :          *
     617                 :          * We can filter out branch 0 or 1 using the next host bit of the
     618                 :          * argument, if it is available.
     619                 :          *
     620                 :          * This check matters for the performance of the search. The results
     621                 :          * would be correct without it.  There is no point in running it for
     622                 :          * leafs as we have to check the whole address on the next step.
     623                 :          */
     624 GIC          54 :         if (!leaf && bitmap & (1 | (1 << 1)) &&
     625 LBC           0 :             commonbits < ip_maxbits(argument))
     626 EUB             :         {
     627                 :             int         nextbit;
     628                 : 
     629 UIC           0 :             nextbit = ip_addr(argument)[commonbits / 8] &
     630 UBC           0 :                 (1 << (7 - commonbits % 8));
     631 EUB             : 
     632 UIC           0 :             switch (strategy)
     633 EUB             :             {
     634 UIC           0 :                 case RTLessStrategyNumber:
     635 EUB             :                 case RTLessEqualStrategyNumber:
     636 UIC           0 :                     if (!nextbit)
     637 UBC           0 :                         bitmap &= 1 | (1 << 2) | (1 << 3);
     638               0 :                     break;
     639 EUB             : 
     640 UIC           0 :                 case RTGreaterEqualStrategyNumber:
     641 EUB             :                 case RTGreaterStrategyNumber:
     642 UIC           0 :                     if (nextbit)
     643 UBC           0 :                         bitmap &= (1 << 1) | (1 << 2) | (1 << 3);
     644               0 :                     break;
     645 EUB             : 
     646 UIC           0 :                 case RTNotEqualStrategyNumber:
     647 UBC           0 :                     break;
     648 EUB             : 
     649 UIC           0 :                 default:
     650 UBC           0 :                     if (!nextbit)
     651               0 :                         bitmap &= 1 | (1 << 2) | (1 << 3);
     652 EUB             :                     else
     653 UIC           0 :                         bitmap &= (1 << 1) | (1 << 2) | (1 << 3);
     654 UBC           0 :                     break;
     655 EUB             :             }
     656                 : 
     657 UIC           0 :             if (!bitmap)
     658 UBC           0 :                 break;
     659 EUB             :         }
     660                 : 
     661                 :         /*
     662                 :          * Check 6: whole address
     663                 :          *
     664                 :          * This is the last check for correctness of the basic comparison
     665                 :          * strategies.  It's only appropriate at leaf entries.
     666                 :          */
     667 GIC          54 :         if (leaf)
     668 ECB             :         {
     669                 :             /* Redo ordering comparison using all address bits */
     670 GIC          54 :             order = bitncmp(ip_addr(prefix), ip_addr(argument),
     671 CBC          54 :                             ip_maxbits(prefix));
     672 ECB             : 
     673 GIC          54 :             switch (strategy)
     674 ECB             :             {
     675 GIC           9 :                 case RTLessStrategyNumber:
     676 CBC           9 :                     if (order >= 0)
     677               9 :                         bitmap = 0;
     678               9 :                     break;
     679 ECB             : 
     680 GIC           9 :                 case RTLessEqualStrategyNumber:
     681 CBC           9 :                     if (order > 0)
     682               6 :                         bitmap = 0;
     683               9 :                     break;
     684 ECB             : 
     685 GIC           9 :                 case RTEqualStrategyNumber:
     686 CBC           9 :                     if (order != 0)
     687               6 :                         bitmap = 0;
     688               9 :                     break;
     689 ECB             : 
     690 GIC           9 :                 case RTGreaterEqualStrategyNumber:
     691 CBC           9 :                     if (order < 0)
     692 LBC           0 :                         bitmap = 0;
     693 GBC           9 :                     break;
     694 ECB             : 
     695 GIC           9 :                 case RTGreaterStrategyNumber:
     696 CBC           9 :                     if (order <= 0)
     697               3 :                         bitmap = 0;
     698               9 :                     break;
     699 ECB             : 
     700 GIC           9 :                 case RTNotEqualStrategyNumber:
     701 CBC           9 :                     if (order == 0)
     702               3 :                         bitmap = 0;
     703               9 :                     break;
     704 ECB             :             }
     705                 : 
     706 GIC          54 :             if (!bitmap)
     707 CBC          27 :                 break;
     708 ECB             :         }
     709                 :     }
     710                 : 
     711 GIC         612 :     return bitmap;
     712 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a