Coverage Report

Created: 2025-08-28 06:29

/src/frr/zebra/zebra_ns.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* zebra NS Routines
3
 * Copyright (C) 2016 Cumulus Networks, Inc.
4
 *                    Donald Sharp
5
 * Copyright (C) 2017/2018 6WIND
6
 */
7
#include "zebra.h"
8
9
#include "lib/ns.h"
10
#include "lib/vrf.h"
11
#include "lib/prefix.h"
12
#include "lib/memory.h"
13
14
#include "zebra_ns.h"
15
#include "zebra_vrf.h"
16
#include "rt.h"
17
#include "zebra_vxlan.h"
18
#include "debug.h"
19
#include "zebra_netns_notify.h"
20
#include "zebra_netns_id.h"
21
#include "zebra_pbr.h"
22
#include "zebra_tc.h"
23
#include "rib.h"
24
#include "table_manager.h"
25
#include "zebra_errors.h"
26
27
extern struct zebra_privs_t zserv_privs;
28
29
DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_NS, "Zebra Name Space");
30
31
static struct zebra_ns *dzns;
32
33
static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete);
34
35
struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id)
36
0
{
37
0
  if (ns_id == NS_DEFAULT)
38
0
    return dzns;
39
0
  struct zebra_ns *info = (struct zebra_ns *)ns_info_lookup(ns_id);
40
41
0
  return (info == NULL) ? dzns : info;
42
0
}
43
44
static struct zebra_ns *zebra_ns_alloc(void)
45
0
{
46
0
  return XCALLOC(MTYPE_ZEBRA_NS, sizeof(struct zebra_ns));
47
0
}
48
49
static int zebra_ns_new(struct ns *ns)
50
0
{
51
0
  struct zebra_ns *zns;
52
53
0
  if (!ns)
54
0
    return -1;
55
56
0
  if (IS_ZEBRA_DEBUG_EVENT)
57
0
    zlog_info("ZNS %s with id %u (created)", ns->name, ns->ns_id);
58
59
0
  zns = zebra_ns_alloc();
60
0
  ns->info = zns;
61
0
  zns->ns = ns;
62
0
  zns->ns_id = ns->ns_id;
63
64
  /* Do any needed per-NS data structure allocation. */
65
0
  zns->if_table = route_table_init();
66
67
0
  return 0;
68
0
}
69
70
static int zebra_ns_delete(struct ns *ns)
71
0
{
72
0
  struct zebra_ns *zns = (struct zebra_ns *)ns->info;
73
74
0
  if (IS_ZEBRA_DEBUG_EVENT)
75
0
    zlog_info("ZNS %s with id %u (deleted)", ns->name, ns->ns_id);
76
0
  if (!zns)
77
0
    return 0;
78
0
  XFREE(MTYPE_ZEBRA_NS, ns->info);
79
0
  return 0;
80
0
}
81
82
static int zebra_ns_enabled(struct ns *ns)
83
0
{
84
0
  struct zebra_ns *zns = ns->info;
85
86
0
  if (IS_ZEBRA_DEBUG_EVENT)
87
0
    zlog_info("ZNS %s with id %u (enabled)", ns->name, ns->ns_id);
88
0
  if (!zns)
89
0
    return 0;
90
0
  return zebra_ns_enable(ns->ns_id, (void **)&zns);
91
0
}
92
93
int zebra_ns_disabled(struct ns *ns)
94
0
{
95
0
  struct zebra_ns *zns = ns->info;
96
97
0
  if (IS_ZEBRA_DEBUG_EVENT)
98
0
    zlog_info("ZNS %s with id %u (disabled)", ns->name, ns->ns_id);
99
0
  if (!zns)
100
0
    return 0;
101
0
  return zebra_ns_disable_internal(zns, true);
102
0
}
103
104
/* Do global enable actions - open sockets, read kernel config etc. */
105
int zebra_ns_enable(ns_id_t ns_id, void **info)
106
0
{
107
0
  struct zebra_ns *zns = (struct zebra_ns *)(*info);
108
109
0
  zns->ns_id = ns_id;
110
111
0
  kernel_init(zns);
112
0
  zebra_dplane_ns_enable(zns, true);
113
0
  interface_list(zns);
114
0
  route_read(zns);
115
116
0
  vlan_read(zns);
117
0
  kernel_read_pbr_rules(zns);
118
0
  kernel_read_tc_qdisc(zns);
119
120
0
  return 0;
121
0
}
122
123
/* Common handler for ns disable - this can be called during ns config,
124
 * or during zebra shutdown.
125
 */
126
static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
127
0
{
128
0
  if (zns->if_table)
129
0
    route_table_finish(zns->if_table);
130
0
  zns->if_table = NULL;
131
132
0
  zebra_dplane_ns_enable(zns, false /*Disable*/);
133
134
0
  kernel_terminate(zns, complete);
135
136
0
  zns->ns_id = NS_DEFAULT;
137
138
0
  return 0;
139
0
}
140
141
/* During zebra shutdown, do partial cleanup while the async dataplane
142
 * is still running.
143
 */
144
int zebra_ns_early_shutdown(struct ns *ns,
145
          void *param_in __attribute__((unused)),
146
          void **param_out __attribute__((unused)))
147
0
{
148
0
  struct zebra_ns *zns = ns->info;
149
150
0
  if (zns == NULL)
151
0
    return 0;
152
153
0
  zebra_ns_disable_internal(zns, false);
154
0
  return NS_WALK_CONTINUE;
155
0
}
156
157
/* During zebra shutdown, do final cleanup
158
 * after all dataplane work is complete.
159
 */
160
int zebra_ns_final_shutdown(struct ns *ns,
161
          void *param_in __attribute__((unused)),
162
          void **param_out __attribute__((unused)))
163
0
{
164
0
  struct zebra_ns *zns = ns->info;
165
166
0
  if (zns == NULL)
167
0
    return 0;
168
169
0
  kernel_terminate(zns, true);
170
171
0
  return NS_WALK_CONTINUE;
172
0
}
173
174
int zebra_ns_init(void)
175
0
{
176
0
  struct ns *default_ns;
177
0
  ns_id_t ns_id;
178
0
  ns_id_t ns_id_external;
179
0
  struct ns *ns;
180
181
0
  frr_with_privs(&zserv_privs) {
182
0
    ns_id = zebra_ns_id_get_default();
183
0
  }
184
0
  ns_id_external = ns_map_nsid_with_external(ns_id, true);
185
0
  ns_init_management(ns_id_external, ns_id);
186
0
  ns = ns_get_default();
187
0
  if (ns)
188
0
    ns->relative_default_ns = ns_id;
189
190
0
  default_ns = ns_lookup(NS_DEFAULT);
191
0
  if (!default_ns) {
192
0
    flog_err(EC_ZEBRA_NS_NO_DEFAULT,
193
0
       "%s: failed to find default ns", __func__);
194
0
    exit(EXIT_FAILURE); /* This is non-recoverable */
195
0
  }
196
197
  /* Do any needed per-NS data structure allocation. */
198
0
  zebra_ns_new(default_ns);
199
0
  dzns = default_ns->info;
200
201
  /* Register zebra VRF callbacks, create and activate default VRF. */
202
0
  zebra_vrf_init();
203
204
  /* Default NS is activated */
205
0
  zebra_ns_enable(ns_id_external, (void **)&dzns);
206
207
0
  if (vrf_is_backend_netns()) {
208
0
    ns_add_hook(NS_NEW_HOOK, zebra_ns_new);
209
0
    ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled);
210
0
    ns_add_hook(NS_DISABLE_HOOK, zebra_ns_disabled);
211
0
    ns_add_hook(NS_DELETE_HOOK, zebra_ns_delete);
212
0
    zebra_ns_notify_parse();
213
0
    zebra_ns_notify_init();
214
0
  }
215
216
0
  return 0;
217
0
}
218
219
int zebra_ns_config_write(struct vty *vty, struct ns *ns)
220
0
{
221
0
  if (ns && ns->name != NULL)
222
0
    vty_out(vty, " netns %s\n", ns->name);
223
0
  return 0;
224
0
}