aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/core/nexthops.h
blob: 232c74388240d53e4029b54f04b9aa2e3f1345a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
 * Copyright (c) 2021-2022 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * \file nexthops.h
 * \brief Nexthops
 *
 * An implementation of the nexthop data structure for the FIB entry.
 *
 * Note that the position of nexthops in this structure can be reordered. This
 * is not an issue for the strategy state since the state if bound to the
 * nexthop information, but an external module should not keep any reference to
 * the offset of the nexthop.
 */

#ifndef HICNLIGHT_NEXTHOPS_H
#define HICNLIGHT_NEXTHOPS_H

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>

#include <hicn/util/log.h>

#include "connection.h"
#include "strategy_vft.h"

#define _nexthops_var(x) _nexthops_##x

typedef unsigned nexthop_t;
#define NEXTHOP(x) ((nexthop_t)x)

#define INVALID_NEXTHOP NEXTHOP(CONNECTION_ID_UNDEFINED)

/*
 * This allows storage within a single integer
 * 32 or 64 nexthops should be sufficient
 * Eventually replace this with a resizeable vector
 */
#define MAX_NEXTHOPS (sizeof(uint_fast32_t) * 8)

typedef struct nexthops_s {
  unsigned elts[MAX_NEXTHOPS];
  strategy_nexthop_state_t state[MAX_NEXTHOPS];
  size_t num_elts;

  /*
   * flags is used during the processing of nexthops by the policy framework,
   * and its meaning is local to the related functions.
   * It is a mask where a bit set to 1 in position N indicates that the Nth
   * elements in the elts array (elts[N]) is disabled.
   * The number of enabled next hops is reflected in cur_elts, and it is equal
   * to num_elts if no nexthop is disabled. This could be replaced by an
   * efficient function counting the number of 1 bits in flags.
   */
  uint_fast32_t flags;
  size_t cur_elts;
} nexthops_t;

#define NEXTHOPS_EMPTY                                                   \
  (nexthops_t) {                                                         \
    .elts = {0}, .state = {STRATEGY_NEXTHOP_STATE_EMPTY}, .num_elts = 0, \
    .flags = 0, .cur_elts = 0,                                           \
  }

#define nexthops_state(NH, i) ((NH)->state[(i)])

#define nexthops_get_len(NH) ((NH)->num_elts)

#define nexthops_set_len(NH, LEN) \
  do {                            \
    (NH)->num_elts = LEN;         \
    (NH)->cur_elts = LEN;         \
  } while (0)

#define nexthops_get_curlen(NH) ((NH)->cur_elts)

#define nexthops_inc(NH) \
  do {                   \
    (NH)->num_elts++;    \
    (NH)->cur_elts++;    \
  } while (0)

int nexthops_disable(nexthops_t *nexthops, off_t offset);
int nexthops_disable_all(nexthops_t *nexthops);

#define nexthops_disable_if(NH, i, condition) \
  do {                                        \
    if (condition) {                          \
      nexthops_disable((NH), (i));            \
    }                                         \
  } while (0)

#define nexthops_is_disabled(NH, i) ((NH)->flags & (1 << (i)))

void nexthops_reset(nexthops_t *nexthops);

#define nexthops_enumerate(NH, I, X, BODY)             \
  do {                                                 \
    nexthop_t X;                                       \
    (void)X;                                           \
    unsigned I;                                        \
    (void)I;                                           \
    for ((I) = 0; (I) < nexthops_get_len(NH); (I)++) { \
      if (nexthops_is_disabled((NH), (I))) continue;   \
      X = (NH)->elts[(I)];                             \
      do {                                             \
        BODY                                           \
      } while (0);                                     \
    }                                                  \
  } while (0)

#define nexthops_foreach(NH, X, BODY)                      \
  do {                                                     \
    nexthops_enumerate((NH), _nexthops_var(i), X, {BODY}); \
  } while (0)

off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop);

off_t nexthops_remove(nexthops_t *nexthops, nexthop_t nexthop);

#define nexthops_clear(NH)   \
  do {                       \
    nexthops_set_len(NH, 0); \
    (NH)->flags = 0;         \
  } while (0)

bool nexthops_contains(nexthops_t *nexthops, unsigned nexthop);

off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop);

unsigned nexthops_get_one(nexthops_t *nexthops);

int nexthops_select(nexthops_t *nexthops, off_t i);

/*
 * This selects the first available element, irrespective of the current state
 * of flags
 */
#define nexthops_select_first(NH) nexthops_select((NH), 0)

#ifdef WITH_POLICY

#define DEFAULT_PRIORITY 0
#define DISABLED_PRIORITY -1

void nexthops_set_priority(nexthops_t *nexthops, nexthop_t nexthop,
                           int priority);

void nexthops_set_priority_by_id(nexthops_t *nexthops, off_t i, int priority);

void nexthops_reset_priority_by_id(nexthops_t *nexthops, off_t i);

void nexthops_reset_priority(nexthops_t *nexthops, nexthop_t nexthop);

void nexthops_reset_priorities(nexthops_t *nexthops);

/*
 * returns true if the list of next hops contained in a is the same of b
 * returns false otherwise
 */
bool nexthops_equal(nexthops_t *a, nexthops_t *b);

void nexthops_copy(nexthops_t *src, nexthops_t *dst);

#endif /* WITH_POLICY */

uint32_t nexthops_get_hash(nexthops_t *nexthops);

#endif /* HICNLIGHT_NEXTHOPS_H */