Line data Source code
1 : /* RIPd and zebra interface.
2 : * Copyright (C) 1997, 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
3 : *
4 : * This file is part of GNU Zebra.
5 : *
6 : * GNU Zebra is free software; you can redistribute it and/or modify it
7 : * under the terms of the GNU General Public License as published by the
8 : * Free Software Foundation; either version 2, or (at your option) any
9 : * later version.
10 : *
11 : * GNU Zebra is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License along
17 : * with this program; see the file COPYING; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : #include <zebra.h>
22 :
23 : #include "command.h"
24 : #include "prefix.h"
25 : #include "table.h"
26 : #include "stream.h"
27 : #include "memory.h"
28 : #include "zclient.h"
29 : #include "log.h"
30 : #include "vrf.h"
31 : #include "ripd/ripd.h"
32 : #include "ripd/rip_debug.h"
33 : #include "ripd/rip_interface.h"
34 :
35 : /* All information about zebra. */
36 : struct zclient *zclient = NULL;
37 :
38 : /* Send ECMP routes to zebra. */
39 20 : static void rip_zebra_ipv4_send(struct rip *rip, struct route_node *rp,
40 : uint8_t cmd)
41 : {
42 20 : struct list *list = (struct list *)rp->info;
43 20 : struct zapi_route api;
44 20 : struct zapi_nexthop *api_nh;
45 20 : struct listnode *listnode = NULL;
46 20 : struct rip_info *rinfo = NULL;
47 20 : int count = 0;
48 :
49 20 : memset(&api, 0, sizeof(api));
50 20 : api.vrf_id = rip->vrf->vrf_id;
51 20 : api.type = ZEBRA_ROUTE_RIP;
52 20 : api.safi = SAFI_UNICAST;
53 :
54 20 : SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
55 40 : for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
56 20 : if (count >= MULTIPATH_NUM)
57 : break;
58 20 : api_nh = &api.nexthops[count];
59 20 : api_nh->vrf_id = rip->vrf->vrf_id;
60 20 : api_nh->gate = rinfo->nh.gate;
61 20 : api_nh->type = NEXTHOP_TYPE_IPV4;
62 20 : if (cmd == ZEBRA_ROUTE_ADD)
63 10 : SET_FLAG(rinfo->flags, RIP_RTF_FIB);
64 : else
65 10 : UNSET_FLAG(rinfo->flags, RIP_RTF_FIB);
66 20 : count++;
67 : }
68 :
69 20 : api.prefix = rp->p;
70 20 : api.nexthop_num = count;
71 :
72 20 : rinfo = listgetdata(listhead(list));
73 :
74 20 : SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
75 20 : api.metric = rinfo->metric;
76 :
77 20 : if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) {
78 0 : SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
79 0 : api.distance = rinfo->distance;
80 : }
81 :
82 20 : if (rinfo->tag) {
83 0 : SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
84 0 : api.tag = rinfo->tag;
85 : }
86 :
87 20 : zclient_route_send(cmd, zclient, &api);
88 :
89 20 : if (IS_RIP_DEBUG_ZEBRA) {
90 0 : if (rip->ecmp)
91 0 : zlog_debug("%s: %pFX nexthops %d",
92 : (cmd == ZEBRA_ROUTE_ADD)
93 : ? "Install into zebra"
94 : : "Delete from zebra",
95 : &rp->p, count);
96 : else
97 0 : zlog_debug("%s: %pFX",
98 : (cmd == ZEBRA_ROUTE_ADD)
99 : ? "Install into zebra"
100 : : "Delete from zebra", &rp->p);
101 : }
102 :
103 20 : rip->counters.route_changes++;
104 20 : }
105 :
106 : /* Add/update ECMP routes to zebra. */
107 10 : void rip_zebra_ipv4_add(struct rip *rip, struct route_node *rp)
108 : {
109 10 : rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_ADD);
110 10 : }
111 :
112 : /* Delete ECMP routes from zebra. */
113 10 : void rip_zebra_ipv4_delete(struct rip *rip, struct route_node *rp)
114 : {
115 10 : rip_zebra_ipv4_send(rip, rp, ZEBRA_ROUTE_DELETE);
116 10 : }
117 :
118 : /* Zebra route add and delete treatment. */
119 11 : static int rip_zebra_read_route(ZAPI_CALLBACK_ARGS)
120 : {
121 11 : struct rip *rip;
122 11 : struct zapi_route api;
123 11 : struct nexthop nh;
124 :
125 11 : rip = rip_lookup_by_vrf_id(vrf_id);
126 11 : if (!rip)
127 : return 0;
128 :
129 11 : if (zapi_route_decode(zclient->ibuf, &api) < 0)
130 : return -1;
131 :
132 11 : memset(&nh, 0, sizeof(nh));
133 11 : nh.type = api.nexthops[0].type;
134 11 : nh.gate.ipv4 = api.nexthops[0].gate.ipv4;
135 11 : nh.ifindex = api.nexthops[0].ifindex;
136 :
137 : /* Then fetch IPv4 prefixes. */
138 11 : if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
139 6 : rip_redistribute_add(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
140 : (struct prefix_ipv4 *)&api.prefix, &nh,
141 6 : api.metric, api.distance, api.tag);
142 5 : else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL)
143 5 : rip_redistribute_delete(rip, api.type, RIP_ROUTE_REDISTRIBUTE,
144 : (struct prefix_ipv4 *)&api.prefix,
145 : nh.ifindex);
146 :
147 : return 0;
148 : }
149 :
150 2 : void rip_redistribute_conf_update(struct rip *rip, int type)
151 : {
152 2 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
153 2 : type, 0, rip->vrf->vrf_id);
154 2 : }
155 :
156 0 : void rip_redistribute_conf_delete(struct rip *rip, int type)
157 : {
158 0 : if (zclient->sock > 0)
159 0 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
160 0 : AFI_IP, type, 0, rip->vrf->vrf_id);
161 :
162 : /* Remove the routes from RIP table. */
163 0 : rip_redistribute_withdraw(rip, type);
164 0 : }
165 :
166 580 : int rip_redistribute_check(struct rip *rip, int type)
167 : {
168 580 : return rip->redist[type].enabled;
169 : }
170 :
171 5 : void rip_redistribute_enable(struct rip *rip)
172 : {
173 160 : for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
174 155 : if (!rip_redistribute_check(rip, i))
175 155 : continue;
176 :
177 0 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
178 0 : i, 0, rip->vrf->vrf_id);
179 : }
180 5 : }
181 :
182 5 : void rip_redistribute_disable(struct rip *rip)
183 : {
184 160 : for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
185 155 : if (!rip_redistribute_check(rip, i))
186 153 : continue;
187 :
188 2 : zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
189 2 : AFI_IP, i, 0, rip->vrf->vrf_id);
190 : }
191 5 : }
192 :
193 9 : void rip_show_redistribute_config(struct vty *vty, struct rip *rip)
194 : {
195 288 : for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
196 279 : if (i == zclient->redist_default
197 270 : || !rip_redistribute_check(rip, i))
198 277 : continue;
199 :
200 2 : vty_out(vty, " %s", zebra_route_string(i));
201 : }
202 9 : }
203 :
204 5 : void rip_zebra_vrf_register(struct vrf *vrf)
205 : {
206 5 : if (vrf->vrf_id == VRF_DEFAULT)
207 : return;
208 :
209 0 : if (IS_RIP_DEBUG_EVENT)
210 0 : zlog_debug("%s: register VRF %s(%u) to zebra", __func__,
211 : vrf->name, vrf->vrf_id);
212 :
213 0 : zclient_send_reg_requests(zclient, vrf->vrf_id);
214 : }
215 :
216 5 : void rip_zebra_vrf_deregister(struct vrf *vrf)
217 : {
218 5 : if (vrf->vrf_id == VRF_DEFAULT)
219 : return;
220 :
221 0 : if (IS_RIP_DEBUG_EVENT)
222 0 : zlog_debug("%s: deregister VRF %s(%u) from zebra.", __func__,
223 : vrf->name, vrf->vrf_id);
224 :
225 0 : zclient_send_dereg_requests(zclient, vrf->vrf_id);
226 : }
227 :
228 5 : static void rip_zebra_connected(struct zclient *zclient)
229 : {
230 5 : zclient_send_reg_requests(zclient, VRF_DEFAULT);
231 5 : }
232 :
233 : zclient_handler *const rip_handlers[] = {
234 : [ZEBRA_INTERFACE_ADDRESS_ADD] = rip_interface_address_add,
235 : [ZEBRA_INTERFACE_ADDRESS_DELETE] = rip_interface_address_delete,
236 : [ZEBRA_INTERFACE_VRF_UPDATE] = rip_interface_vrf_update,
237 : [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = rip_zebra_read_route,
238 : [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = rip_zebra_read_route,
239 : };
240 :
241 5 : void rip_zclient_init(struct thread_master *master)
242 : {
243 : /* Set default value to the zebra client structure. */
244 5 : zclient = zclient_new(master, &zclient_options_default, rip_handlers,
245 : array_size(rip_handlers));
246 5 : zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs);
247 5 : zclient->zebra_connected = rip_zebra_connected;
248 5 : }
249 :
250 5 : void rip_zclient_stop(void)
251 : {
252 5 : zclient_stop(zclient);
253 5 : zclient_free(zclient);
254 5 : }
|