]>
Commit | Line | Data |
---|---|---|
1 | /* zebra NS Routines | |
2 | * Copyright (C) 2016 Cumulus Networks, Inc. | |
3 | * Donald Sharp | |
4 | * Copyright (C) 2017/2018 6WIND | |
5 | * | |
6 | * This file is part of Quagga. | |
7 | * | |
8 | * Quagga is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2, or (at your option) any | |
11 | * later version. | |
12 | * | |
13 | * Quagga is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License along | |
19 | * with this program; see the file COPYING; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | */ | |
22 | #include "zebra.h" | |
23 | ||
24 | #include "lib/ns.h" | |
25 | #include "lib/vrf.h" | |
26 | #include "lib/prefix.h" | |
27 | #include "lib/memory.h" | |
28 | ||
29 | #include "zebra_ns.h" | |
30 | #include "zebra_vrf.h" | |
31 | #include "zebra_memory.h" | |
32 | #include "rt.h" | |
33 | #include "zebra_vxlan.h" | |
34 | #include "debug.h" | |
35 | #include "zebra_netns_notify.h" | |
36 | #include "zebra_netns_id.h" | |
37 | #include "zebra_pbr.h" | |
38 | #include "rib.h" | |
39 | #include "table_manager.h" | |
40 | #include "zebra_errors.h" | |
41 | ||
42 | extern struct zebra_privs_t zserv_privs; | |
43 | ||
44 | DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") | |
45 | ||
46 | static struct zebra_ns *dzns; | |
47 | ||
48 | static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete); | |
49 | ||
50 | struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id) | |
51 | { | |
52 | if (ns_id == NS_DEFAULT) | |
53 | return dzns; | |
54 | struct zebra_ns *info = (struct zebra_ns *)ns_info_lookup(ns_id); | |
55 | ||
56 | return (info == NULL) ? dzns : info; | |
57 | } | |
58 | ||
59 | static struct zebra_ns *zebra_ns_alloc(void) | |
60 | { | |
61 | return XCALLOC(MTYPE_ZEBRA_NS, sizeof(struct zebra_ns)); | |
62 | } | |
63 | ||
64 | static int zebra_ns_new(struct ns *ns) | |
65 | { | |
66 | struct zebra_ns *zns; | |
67 | ||
68 | if (!ns) | |
69 | return -1; | |
70 | ||
71 | if (IS_ZEBRA_DEBUG_EVENT) | |
72 | zlog_info("ZNS %s with id %u (created)", ns->name, ns->ns_id); | |
73 | ||
74 | zns = zebra_ns_alloc(); | |
75 | ns->info = zns; | |
76 | zns->ns = ns; | |
77 | zns->ns_id = ns->ns_id; | |
78 | ||
79 | /* Do any needed per-NS data structure allocation. */ | |
80 | zns->if_table = route_table_init(); | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
85 | static int zebra_ns_delete(struct ns *ns) | |
86 | { | |
87 | struct zebra_ns *zns = (struct zebra_ns *)ns->info; | |
88 | ||
89 | if (IS_ZEBRA_DEBUG_EVENT) | |
90 | zlog_info("ZNS %s with id %u (deleted)", ns->name, ns->ns_id); | |
91 | if (!zns) | |
92 | return 0; | |
93 | XFREE(MTYPE_ZEBRA_NS, ns->info); | |
94 | return 0; | |
95 | } | |
96 | ||
97 | static int zebra_ns_enabled(struct ns *ns) | |
98 | { | |
99 | struct zebra_ns *zns = ns->info; | |
100 | ||
101 | if (IS_ZEBRA_DEBUG_EVENT) | |
102 | zlog_info("ZNS %s with id %u (enabled)", ns->name, ns->ns_id); | |
103 | if (!zns) | |
104 | return 0; | |
105 | return zebra_ns_enable(ns->ns_id, (void **)&zns); | |
106 | } | |
107 | ||
108 | int zebra_ns_disabled(struct ns *ns) | |
109 | { | |
110 | struct zebra_ns *zns = ns->info; | |
111 | ||
112 | if (IS_ZEBRA_DEBUG_EVENT) | |
113 | zlog_info("ZNS %s with id %u (disabled)", ns->name, ns->ns_id); | |
114 | if (!zns) | |
115 | return 0; | |
116 | return zebra_ns_disable_internal(zns, true); | |
117 | } | |
118 | ||
119 | /* Do global enable actions - open sockets, read kernel config etc. */ | |
120 | int zebra_ns_enable(ns_id_t ns_id, void **info) | |
121 | { | |
122 | struct zebra_ns *zns = (struct zebra_ns *)(*info); | |
123 | ||
124 | zns->ns_id = ns_id; | |
125 | ||
126 | kernel_init(zns); | |
127 | interface_list(zns); | |
128 | route_read(zns); | |
129 | ||
130 | /* Initiate Table Manager per ZNS */ | |
131 | table_manager_enable(ns_id); | |
132 | ||
133 | return 0; | |
134 | } | |
135 | ||
136 | /* Common handler for ns disable - this can be called during ns config, | |
137 | * or during zebra shutdown. | |
138 | */ | |
139 | static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete) | |
140 | { | |
141 | route_table_finish(zns->if_table); | |
142 | ||
143 | kernel_terminate(zns, complete); | |
144 | ||
145 | table_manager_disable(zns->ns_id); | |
146 | ||
147 | zns->ns_id = NS_DEFAULT; | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
152 | /* During zebra shutdown, do partial cleanup while the async dataplane | |
153 | * is still running. | |
154 | */ | |
155 | int zebra_ns_early_shutdown(struct ns *ns) | |
156 | { | |
157 | struct zebra_ns *zns = ns->info; | |
158 | ||
159 | if (zns == NULL) | |
160 | return 0; | |
161 | ||
162 | return zebra_ns_disable_internal(zns, false); | |
163 | } | |
164 | ||
165 | /* During zebra shutdown, do final cleanup | |
166 | * after all dataplane work is complete. | |
167 | */ | |
168 | int zebra_ns_final_shutdown(struct ns *ns) | |
169 | { | |
170 | struct zebra_ns *zns = ns->info; | |
171 | ||
172 | if (zns == NULL) | |
173 | return 0; | |
174 | ||
175 | kernel_terminate(zns, true); | |
176 | ||
177 | return 0; | |
178 | } | |
179 | ||
180 | int zebra_ns_init(const char *optional_default_name) | |
181 | { | |
182 | struct ns *default_ns; | |
183 | ns_id_t ns_id; | |
184 | ns_id_t ns_id_external; | |
185 | ||
186 | frr_with_privs(&zserv_privs) { | |
187 | ns_id = zebra_ns_id_get_default(); | |
188 | } | |
189 | ns_id_external = ns_map_nsid_with_external(ns_id, true); | |
190 | ns_init_management(ns_id_external, ns_id); | |
191 | ||
192 | default_ns = ns_lookup(ns_get_default_id()); | |
193 | if (!default_ns) { | |
194 | flog_err(EC_ZEBRA_NS_NO_DEFAULT, | |
195 | "%s: failed to find default ns", __func__); | |
196 | exit(EXIT_FAILURE); /* This is non-recoverable */ | |
197 | } | |
198 | ||
199 | /* Do any needed per-NS data structure allocation. */ | |
200 | zebra_ns_new(default_ns); | |
201 | dzns = default_ns->info; | |
202 | ||
203 | /* Register zebra VRF callbacks, create and activate default VRF. */ | |
204 | zebra_vrf_init(); | |
205 | ||
206 | /* Default NS is activated */ | |
207 | zebra_ns_enable(ns_id_external, (void **)&dzns); | |
208 | ||
209 | if (optional_default_name) | |
210 | vrf_set_default_name(optional_default_name, | |
211 | true); | |
212 | ||
213 | if (vrf_is_backend_netns()) { | |
214 | ns_add_hook(NS_NEW_HOOK, zebra_ns_new); | |
215 | ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled); | |
216 | ns_add_hook(NS_DISABLE_HOOK, zebra_ns_disabled); | |
217 | ns_add_hook(NS_DELETE_HOOK, zebra_ns_delete); | |
218 | zebra_ns_notify_parse(); | |
219 | zebra_ns_notify_init(); | |
220 | } | |
221 | ||
222 | return 0; | |
223 | } | |
224 | ||
225 | int zebra_ns_config_write(struct vty *vty, struct ns *ns) | |
226 | { | |
227 | if (ns && ns->name != NULL) | |
228 | vty_out(vty, " netns %s\n", ns->name); | |
229 | return 0; | |
230 | } |