]> git.proxmox.com Git - mirror_frr.git/blob - ospfclient/ospfclient.c
lib: more `show thread cpu`
[mirror_frr.git] / ospfclient / ospfclient.c
1 /* This file is part of Quagga.
2 *
3 * Quagga is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the
5 * Free Software Foundation; either version 2, or (at your option) any
6 * later version.
7 *
8 * Quagga is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; see the file COPYING; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 /*
19 * Simple program to demonstrate how OSPF API can be used. This
20 * application retrieves the LSDB from the OSPF daemon and then
21 * originates, updates and finally deletes an application-specific
22 * opaque LSA. You can use this application as a template when writing
23 * your own application.
24 */
25
26 /* The following includes are needed in all OSPF API client
27 applications. */
28
29 #include <zebra.h>
30 #include "prefix.h" /* needed by ospf_asbr.h */
31 #include "privs.h"
32 #include "log.h"
33
34 /* work around gcc bug 69981, disable MTYPEs in libospf */
35 #define _QUAGGA_OSPF_MEMORY_H
36
37 #include "ospfd/ospfd.h"
38 #include "ospfd/ospf_asbr.h"
39 #include "ospfd/ospf_lsa.h"
40 #include "ospfd/ospf_opaque.h"
41 #include "ospfd/ospf_api.h"
42 #include "ospf_apiclient.h"
43
44 /* privileges struct.
45 * set cap_num_* and uid/gid to nothing to use NULL privs
46 * as ospfapiclient links in libospf.a which uses privs.
47 */
48 struct zebra_privs_t ospfd_privs =
49 {
50 .user = NULL,
51 .group = NULL,
52 .cap_num_p = 0,
53 .cap_num_i = 0
54 };
55
56 /* The following includes are specific to this application. For
57 example it uses threads from libfrr, however your application is
58 free to use any thread library (like pthreads). */
59
60 #include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
61 #include "thread.h"
62 #include "log.h"
63
64 /* Local portnumber for async channel. Note that OSPF API library will also
65 allocate a sync channel at ASYNCPORT+1. */
66 #define ASYNCPORT 4000
67
68 /* Master thread */
69 struct thread_master *master;
70
71 /* Global variables */
72 struct ospf_apiclient *oclient;
73 char **args;
74
75 /* Our opaque LSAs have the following format. */
76 struct my_opaque_lsa
77 {
78 struct lsa_header hdr; /* include common LSA header */
79 u_char data[4]; /* our own data format then follows here */
80 };
81
82
83 /* ---------------------------------------------------------
84 * Threads for asynchronous messages and LSA update/delete
85 * ---------------------------------------------------------
86 */
87
88 static int
89 lsa_delete (struct thread *t)
90 {
91 struct ospf_apiclient *oclient;
92 struct in_addr area_id;
93 int rc;
94
95 oclient = THREAD_ARG (t);
96
97 rc = inet_aton (args[6], &area_id);
98 if (rc <= 0)
99 {
100 printf("Address Specified: %s is invalid\n", args[6]);
101 return rc;
102 }
103
104 printf ("Deleting LSA... ");
105 rc = ospf_apiclient_lsa_delete (oclient,
106 area_id,
107 atoi (args[2]), /* lsa type */
108 atoi (args[3]), /* opaque type */
109 atoi (args[4])); /* opaque ID */
110 printf ("done, return code is = %d\n", rc);
111 return rc;
112 }
113
114 static int
115 lsa_inject (struct thread *t)
116 {
117 struct ospf_apiclient *cl;
118 struct in_addr ifaddr;
119 struct in_addr area_id;
120 u_char lsa_type;
121 u_char opaque_type;
122 u_int32_t opaque_id;
123 void *opaquedata;
124 int opaquelen;
125
126 static u_int32_t counter = 1; /* Incremented each time invoked */
127 int rc;
128
129 cl = THREAD_ARG (t);
130
131 rc = inet_aton (args[5], &ifaddr);
132 if (rc <= 0)
133 {
134 printf ("Ifaddr specified %s is invalid\n", args[5]);
135 return rc;
136 }
137
138 rc = inet_aton (args[6], &area_id);
139 if (rc <= 0)
140 {
141 printf( "Area ID specified %s is invalid\n", args[6]);
142 return rc;
143 }
144 lsa_type = atoi (args[2]);
145 opaque_type = atoi (args[3]);
146 opaque_id = atoi (args[4]);
147 opaquedata = &counter;
148 opaquelen = sizeof (u_int32_t);
149
150 printf ("Originating/updating LSA with counter=%d... ", counter);
151 rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
152 lsa_type,
153 opaque_type, opaque_id,
154 opaquedata, opaquelen);
155
156 printf ("done, return code is %d\n", rc);
157
158 counter++;
159
160 return 0;
161 }
162
163
164 /* This thread handles asynchronous messages coming in from the OSPF
165 API server */
166 static int
167 lsa_read (struct thread *thread)
168 {
169 struct ospf_apiclient *oclient;
170 int fd;
171 int ret;
172
173 printf ("lsa_read called\n");
174
175 oclient = THREAD_ARG (thread);
176 fd = THREAD_FD (thread);
177
178 /* Handle asynchronous message */
179 ret = ospf_apiclient_handle_async (oclient);
180 if (ret < 0) {
181 printf ("Connection closed, exiting...");
182 exit(0);
183 }
184
185 /* Reschedule read thread */
186 thread_add_read(master, lsa_read, oclient, fd, NULL);
187
188 return 0;
189 }
190
191 /* ---------------------------------------------------------
192 * Callback functions for asynchronous events
193 * ---------------------------------------------------------
194 */
195
196 static void
197 lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
198 u_char is_self_originated,
199 struct lsa_header *lsa)
200 {
201 printf ("lsa_update_callback: ");
202 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
203 printf ("area: %s\n", inet_ntoa (area_id));
204 printf ("is_self_origin: %u\n", is_self_originated);
205
206 /* It is important to note that lsa_header does indeed include the
207 header and the LSA payload. To access the payload, first check
208 the LSA type and then typecast lsa into the corresponding type,
209 e.g.:
210
211 if (lsa->type == OSPF_ROUTER_LSA) {
212 struct router_lsa *rl = (struct router_lsa) lsa;
213 ...
214 u_int16_t links = rl->links;
215 ...
216 }
217 */
218
219 ospf_lsa_header_dump (lsa);
220 }
221
222 static void
223 lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
224 u_char is_self_originated,
225 struct lsa_header *lsa)
226 {
227 printf ("lsa_delete_callback: ");
228 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
229 printf ("area: %s\n", inet_ntoa (area_id));
230 printf ("is_self_origin: %u\n", is_self_originated);
231
232 ospf_lsa_header_dump (lsa);
233 }
234
235 static void
236 ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
237 {
238 printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
239 lsa_type, opaque_type, inet_ntoa (addr));
240
241 /* Schedule opaque LSA originate in 5 secs */
242 thread_add_timer(master, lsa_inject, oclient, 5, NULL);
243
244 /* Schedule opaque LSA update with new value */
245 thread_add_timer(master, lsa_inject, oclient, 10, NULL);
246
247 /* Schedule delete */
248 thread_add_timer(master, lsa_delete, oclient, 30, NULL);
249 }
250
251 static void
252 new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
253 {
254 printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
255 printf ("area_id: %s\n", inet_ntoa (area_id));
256 }
257
258 static void
259 del_if_callback (struct in_addr ifaddr)
260 {
261 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
262 }
263
264 static void
265 ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
266 u_char state)
267 {
268 printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
269 printf ("area_id: %s\n", inet_ntoa (area_id));
270 printf ("state: %d [%s]\n", state, lookup_msg(ospf_ism_state_msg, state, NULL));
271 }
272
273 static void
274 nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
275 struct in_addr router_id, u_char state)
276 {
277 printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
278 printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
279 printf ("router_id: %s\n", inet_ntoa (router_id));
280 printf ("state: %d [%s]\n", state, lookup_msg(ospf_nsm_state_msg, state, NULL));
281 }
282
283
284 /* ---------------------------------------------------------
285 * Main program
286 * ---------------------------------------------------------
287 */
288
289 static int usage(void)
290 {
291 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
292 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
293 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
294 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
295 printf(" opaqueid : arbitrary application instance (24 bits)\n");
296 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
297 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
298
299 exit(1);
300 }
301
302 int
303 main (int argc, char *argv[])
304 {
305 struct thread thread;
306
307 args = argv;
308
309 /* ospfclient should be started with the following arguments:
310 *
311 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
312 * (6) area_id
313 *
314 * host: name or IP of host where ospfd is running
315 * lsa_type: 9, 10, or 11
316 * opaque_type: 0-255 (e.g., experimental applications use > 128)
317 * opaque_id: arbitrary application instance (24 bits)
318 * if_addr: interface IP address (for type 9) otherwise ignored
319 * area_id: area in IP address format (for type 10) otherwise ignored
320 */
321
322 if (argc != 7)
323 {
324 usage();
325 }
326
327 /* Initialization */
328 zprivs_init (&ospfd_privs);
329 master = thread_master_create(NULL);
330
331 /* Open connection to OSPF daemon */
332 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
333 if (!oclient)
334 {
335 printf ("Connecting to OSPF daemon on %s failed!\n",
336 args[1]);
337 exit (1);
338 }
339
340 /* Register callback functions. */
341 ospf_apiclient_register_callback (oclient,
342 ready_callback,
343 new_if_callback,
344 del_if_callback,
345 ism_change_callback,
346 nsm_change_callback,
347 lsa_update_callback,
348 lsa_delete_callback);
349
350 /* Register LSA type and opaque type. */
351 ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
352 atoi (args[3]));
353
354 /* Synchronize database with OSPF daemon. */
355 ospf_apiclient_sync_lsdb (oclient);
356
357 /* Schedule thread that handles asynchronous messages */
358 thread_add_read(master, lsa_read, oclient, oclient->fd_async, NULL);
359
360 /* Now connection is established, run loop */
361 while (1)
362 {
363 thread_fetch (master, &thread);
364 thread_call (&thread);
365 }
366
367 /* Never reached */
368 return 0;
369 }
370