Annotation of embedaddon/pimd/rsrr.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1993, 1998-2001.
3: * The University of Southern California/Information Sciences Institute.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. Neither the name of the project nor the names of its contributors
15: * may be used to endorse or promote products derived from this software
16: * without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: */
30:
31: /* RSRR code written by Daniel Zappala, USC Information Sciences Institute,
32: * April 1995.
33: */
34:
35: /* May 1995 -- Added support for Route Change Notification */
36:
37: #ifdef RSRR
38:
39: #include "defs.h"
40: #include <sys/param.h>
41: #ifdef HAVE_SA_LEN
42: #include <stddef.h> /* for offsetof */
43: #endif
44:
45: /*
46: * Local RSRR variables.
47: */
48: static int rsrr_socket; /* interface to reservation protocol */
49: static char *rsrr_recv_buf; /* RSRR receive buffer */
50: static char *rsrr_send_buf; /* RSRR send buffer */
51:
52: static struct sockaddr_un client_addr;
53: static socklen_t client_length = sizeof(client_addr);
54:
55: /*
56: * Procedure definitions needed internally.
57: */
58: static void rsrr_accept (size_t recvlen);
59: static void rsrr_accept_iq (void);
60: static int rsrr_accept_rq (struct rsrr_rq *route_query, uint8_t flags, struct gtable *gt_notify);
61: static void rsrr_read (int, fd_set *);
62: static int rsrr_send (int sendlen);
63: static void rsrr_cache (struct gtable *gt, struct rsrr_rq *route_query);
64:
65: /* Initialize RSRR socket */
66: void rsrr_init(void)
67: {
68: int servlen;
69: struct sockaddr_un serv_addr;
70:
71: rsrr_recv_buf = (char *)calloc(1, RSRR_MAX_LEN);
72: rsrr_send_buf = (char *)calloc(1, RSRR_MAX_LEN);
73: if (!rsrr_recv_buf || !rsrr_send_buf)
74: logit(LOG_ERR, 0, "Ran out of memory in rsrr_init()");
75:
76: if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
77: logit(LOG_ERR, errno, "Cannot create RSRR socket");
78:
79: unlink(RSRR_SERV_PATH);
80: memset(&serv_addr, 0, sizeof(serv_addr));
81: serv_addr.sun_family = AF_UNIX;
82: strlcpy(serv_addr.sun_path, RSRR_SERV_PATH, sizeof(serv_addr.sun_path));
83: #ifdef HAVE_SA_LEN
84: servlen = offsetof(struct sockaddr_un, sun_path) + strlen(serv_addr.sun_path);
85: serv_addr.sun_len = servlen;
86: #else
87: servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
88: #endif
89:
90: if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
91: logit(LOG_ERR, errno, "Cannot bind RSRR socket");
92:
93: if (register_input_handler(rsrr_socket, rsrr_read) < 0)
94: logit(LOG_ERR, 0, "Could not register RSRR as an input handler");
95: }
96:
97: /* Read a message from the RSRR socket */
98: static void rsrr_read(int fd, fd_set *rfd __attribute__ ((unused)))
99: {
100: ssize_t len;
101:
102: memset(&client_addr, 0, sizeof(client_addr));
103: while ((len = recvfrom(fd, rsrr_recv_buf, sizeof(rsrr_recv_buf),
104: 0, (struct sockaddr *)&client_addr, &client_length)) < 0) {
105: if (errno == EINTR)
106: continue; /* Received signal, retry syscall. */
107:
108: logit(LOG_ERR, errno, "Failed recvfrom() in rsrr_read()");
109: return;
110: }
111:
112: rsrr_accept(len);
113: }
114:
115: /* Accept a message from the reservation protocol and take
116: * appropriate action.
117: */
118: static void rsrr_accept(size_t recvlen)
119: {
120: struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_recv_buf;
121: struct rsrr_rq *route_query;
122:
123: if (recvlen < RSRR_HEADER_LEN) {
124: logit(LOG_WARNING, 0, "Received RSRR packet of %d bytes, which is less than MIN size %d.",
125: recvlen, RSRR_HEADER_LEN);
126: return;
127: }
128:
129: if (rsrr->version > RSRR_MAX_VERSION || rsrr->version != 1) {
130: logit(LOG_WARNING, 0, "Received RSRR packet version %d, which I don't understand",
131: rsrr->version);
132: return;
133: }
134:
135: switch (rsrr->type) {
136: case RSRR_INITIAL_QUERY:
137: /* Send Initial Reply to client */
138: IF_DEBUG(DEBUG_RSRR) {
139: logit(LOG_DEBUG, 0, "Received Initial Query\n");
140: }
141: rsrr_accept_iq();
142: break;
143:
144: case RSRR_ROUTE_QUERY:
145: /* Check size */
146: if (recvlen < RSRR_RQ_LEN) {
147: logit(LOG_WARNING, 0, "Received Route Query of %d bytes, which is too small", recvlen);
148: break;
149: }
150: /* Get the query */
151: route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
152: IF_DEBUG(DEBUG_RSRR) {
153: logit(LOG_DEBUG, 0,
154: "Received Route Query for src %s grp %s notification %d",
155: inet_fmt(route_query->source_addr, s1, sizeof(s1)),
156: inet_fmt(route_query->dest_addr, s2, sizeof(s2)),
157: BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT));
158: }
159: /* Send Route Reply to client */
160: rsrr_accept_rq(route_query, rsrr->flags, NULL);
161: break;
162:
163: default:
164: logit(LOG_WARNING, 0, "Received RSRR packet type %d, which I don't handle", rsrr->type);
165: break;
166: }
167: }
168:
169: /* Send an Initial Reply to the reservation protocol. */
170: /*
171: * TODO: XXX: if a new interfaces come up and _IF_ the multicast routing
172: * daemon automatically include it, have to inform the RSVP daemon.
173: * However, this is not in the RSRRv1 draft (just expired and is not
174: * available anymore from the internet-draft ftp sites). Probably has to
175: * be included in RSRRv2.
176: */
177: static void rsrr_accept_iq(void)
178: {
179: struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_send_buf;
180: struct rsrr_vif *vif_list;
181: struct uvif *v;
182: vifi_t vifi;
183: int sendlen;
184:
185: /* Check for space. There should be room for plenty of vifs,
186: * but we should check anyway.
187: */
188: if (numvifs > RSRR_MAX_VIFS) {
189: logit(LOG_WARNING, 0,
190: "Cannot send RSRR Route Reply because %d is too many vifs %d",
191: numvifs);
192: return;
193: }
194:
195: /* Set up message */
196: rsrr->version = 1;
197: rsrr->type = RSRR_INITIAL_REPLY;
198: rsrr->flags = 0;
199: rsrr->num = numvifs;
200:
201: vif_list = (struct rsrr_vif *)(rsrr_send_buf + RSRR_HEADER_LEN);
202:
203: /* Include the vif list. */
204: for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
205: vif_list[vifi].id = vifi;
206: vif_list[vifi].status = 0;
207: if (v->uv_flags & VIFF_DISABLED)
208: BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT);
209: vif_list[vifi].threshold = v->uv_threshold;
210: vif_list[vifi].local_addr = v->uv_lcl_addr;
211: }
212:
213: /* Get the size. */
214: sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
215:
216: /* Send it. */
217: IF_DEBUG(DEBUG_RSRR) {
218: logit(LOG_DEBUG, 0, "Send RSRR Initial Reply");
219: }
220: rsrr_send(sendlen);
221: }
222:
223: /* Send a Route Reply to the reservation protocol. The Route Query
224: * contains the query to which we are responding. The flags contain
225: * the incoming flags from the query or, for route change
226: * notification, the flags that should be set for the reply. The
227: * kernel table entry contains the routing info to use for a route
228: * change notification.
229: */
230: /* XXX: must modify if your routing table structure/search is different */
231: static int rsrr_accept_rq(struct rsrr_rq *route_query, uint8_t flags, struct gtable *gt_notify)
232: {
233: struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_send_buf;
234: struct rsrr_rr *route_reply;
235: int sendlen;
236: struct gtable *gt;
237: int status_ok;
238: #ifdef PIM
239: int found;
240: uint8_t tmp_flags;
241: rp_grp_entry_t *rp_grp_entry;
242: grpentry_t *grpentry_ptr;
243: #else
244: struct gtable local_g;
245: struct rtentry *r;
246: uint32_t mcastgrp;
247: #endif /* PIM */
248:
249: /* Set up message */
250: rsrr->version = 1;
251: rsrr->type = RSRR_ROUTE_REPLY;
252: rsrr->flags = flags;
253: rsrr->num = 0;
254:
255: route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
256: route_reply->dest_addr = route_query->dest_addr;
257: route_reply->source_addr = route_query->source_addr;
258: route_reply->query_id = route_query->query_id;
259:
260: /* Blank routing entry for error. */
261: route_reply->in_vif = 0;
262: route_reply->reserved = 0;
263: route_reply->out_vif_bm = 0;
264:
265: /* Get the size. */
266: sendlen = RSRR_RR_LEN;
267:
268: /* If routing table entry is defined, then we are sending a Route Reply
269: * due to a Route Change Notification event. Use the routing table entry
270: * to supply the routing info.
271: */
272: status_ok = FALSE;
273: #ifdef PIM
274: if (gt_notify) {
275: /* Include the routing entry. */
276: route_reply->in_vif = gt_notify->incoming;
277: route_reply->out_vif_bm = gt_notify->oifs;
278: gt = gt_notify;
279: status_ok = TRUE;
280: } else if ((gt = find_route(route_query->source_addr,
281: route_query->dest_addr,
282: MRTF_SG | MRTF_WC | MRTF_PMBR,
283: DONT_CREATE)) != (struct gtable *)NULL) {
284: status_ok = TRUE;
285: route_reply->in_vif = gt->incoming;
286: route_reply->out_vif_bm = gt->oifs;
287: }
288: if (status_ok != TRUE) {
289: /* Set error bit. */
290: rsrr->flags = 0;
291: BIT_SET(rsrr->flags, RSRR_ERROR_BIT);
292: }
293: else {
294: if (gt->flags & (MRTF_WC | MRTF_PMBR)) {
295: tmp_flags = 0;
296: BIT_SET(tmp_flags, RSRR_THIS_SENDER_SHARED_TREE);
297: BIT_SET(tmp_flags, RSRR_ALL_SENDERS_SHARED_TREE);
298: if (!(flags & tmp_flags)) {
299: /* Check whether need to setup the (*,G) related flags */
300: found = FALSE;
301: if (gt->flags & MRTF_PMBR) {
302: /* Check whether there is at least one (S,G) entry which is
303: * a longer match than this (*,*,RP) entry.
304: */
305: for (rp_grp_entry = gt->source->cand_rp->rp_grp_next;
306: rp_grp_entry != (rp_grp_entry_t *)NULL;
307: rp_grp_entry = rp_grp_entry->rp_grp_next) {
308: for (grpentry_ptr = rp_grp_entry->grplink;
309: grpentry_ptr != (grpentry_t *)NULL;
310: grpentry_ptr = grpentry_ptr->rpnext) {
311: if (grpentry_ptr->mrtlink != (mrtentry_t *)NULL) {
312: found = TRUE;
313: break;
314: }
315: }
316: if (found == TRUE)
317: break;
318: }
319: }
320: else if (gt->flags & MRTF_WC) {
321: if (gt->group->mrtlink != (mrtentry_t *)NULL)
322: found = TRUE;
323: }
324: if (found == TRUE) {
325: RSRR_THIS_SENDER_SHARED_TREE_SOME_OTHER_NOT(rsrr->flags);
326: }
327: else {
328: RSRR_SET_ALL_SENDERS_SHARED_TREE(rsrr->flags);
329: }
330: }
331: }
332: /* Cache reply if using route change notification. */
333: if (BIT_TST(flags, RSRR_NOTIFICATION_BIT)) {
334: /* TODO: XXX: Originally the rsrr_cache() call was first, but
335: * I think this is incorrect, because rsrr_cache() checks the
336: * rsrr_send_buf "flag" first.
337: */
338: BIT_SET(rsrr->flags, RSRR_NOTIFICATION_BIT);
339: rsrr_cache(gt, route_query);
340: }
341: }
342: #else /* Not PIM */
343: if (gt_notify) {
344: /* Set flags */
345: rsrr->flags = flags;
346: /* Include the routing entry. */
347: /* The original code from mrouted-3.9b2 */
348: route_reply->in_vif = gt_notify->gt_route->rt_parent;
349: /* TODO: XXX: bug? See the PIM code above */
350: if (BIT_TST(flags, RSRR_NOTIFICATION_BIT))
351: route_reply->out_vif_bm = gt_notify->gt_grpmems;
352: else
353: route_reply->out_vif_bm = 0;
354: } else if (find_src_grp(route_query->source_addr, 0,
355: route_query->dest_addr)) {
356:
357: /* Found kernel entry. Code taken from add_table_entry() */
358: gt = gtp ? gtp->gt_gnext : kernel_table;
359:
360: /* Include the routing entry. */
361: route_reply->in_vif = gt->gt_route->rt_parent;
362: route_reply->out_vif_bm = gt->gt_grpmems;
363:
364: /* Cache reply if using route change notification. */
365: if (BIT_TST(flags, RSRR_NOTIFICATION_BIT)) {
366: /* TODO: XXX: Originally the rsrr_cache() call was first, but
367: * I think this is incorrect, because rsrr_cache() checks the
368: * rsrr_send_buf "flag" first.
369: */
370: BIT_SET(rsrr->flags, RSRR_NOTIFICATION_BIT);
371: rsrr_cache(gt, route_query);
372: }
373: } else {
374: /* No kernel entry; use routing table. */
375: r = determine_route(route_query->source_addr);
376:
377: if (r != NULL) {
378: /* We need to mimic what will happen if a data packet
379: * is forwarded by multicast routing -- the kernel will
380: * make an upcall and mrouted will install a route in the kernel.
381: * Our outgoing vif bitmap should reflect what that table
382: * will look like. Grab code from add_table_entry().
383: * This is gross, but it's probably better to be accurate.
384: */
385:
386: gt = &local_g;
387: mcastgrp = route_query->dest_addr;
388:
389: gt->gt_mcastgrp = mcastgrp;
390: gt->gt_grpmems = 0;
391: gt->gt_scope = 0;
392: gt->gt_route = r;
393:
394: /* obtain the multicast group membership list */
395: determine_forwvifs(gt);
396:
397: /* Include the routing entry. */
398: route_reply->in_vif = gt->gt_route->rt_parent;
399: route_reply->out_vif_bm = gt->gt_grpmems;
400: } else {
401: /* Set error bit. */
402: BIT_SET(rsrr->flags, RSRR_ERROR_BIT);
403: }
404: }
405: #endif /* pimd - mrouted specific code */
406:
407: IF_DEBUG(DEBUG_RSRR) {
408: logit(LOG_DEBUG, 0, "%sSend RSRR Route Reply for src %s dst %s in vif %d out vif %d\n",
409: gt_notify ? "Route Change: " : "",
410: inet_fmt(route_reply->source_addr, s1, sizeof(s1)),
411: inet_fmt(route_reply->dest_addr, s2, sizeof(s2)),
412: route_reply->in_vif,route_reply->out_vif_bm);
413: }
414:
415: /* Send it. */
416: return rsrr_send(sendlen);
417: }
418:
419: /* Send an RSRR message. */
420: static int rsrr_send(int sendlen)
421: {
422: int error;
423:
424: while ((error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
425: (struct sockaddr *)&client_addr, client_length)) < 0)
426: {
427: if (errno == EINTR)
428: continue; /* Received signal, retry syscall. */
429:
430: logit(LOG_WARNING, errno, "Failed sendto() in rsrr_send()");
431:
432: return error;
433: }
434:
435: if (error != sendlen)
436: logit(LOG_WARNING, 0, "Sent only %d out of %d bytes on RSRR socket", error, sendlen);
437:
438: return error;
439: }
440:
441: /* TODO: need to sort the rsrr_cache entries for faster access */
442: /* Cache a message being sent to a client. Currently only used for
443: * caching Route Reply messages for route change notification.
444: */
445: static void rsrr_cache(struct gtable *gt, struct rsrr_rq *route_query)
446: {
447: struct rsrr_cache *rc, **rcnp;
448: struct rsrr_header *rsrr = (struct rsrr_header *)rsrr_send_buf;
449:
450: #ifdef PIM
451: rcnp = >->rsrr_cache;
452: #else
453: rcnp = >->gt_rsrr_cache;
454: #endif /* PIM */
455: while ((rc = *rcnp) != NULL) {
456: if ((rc->route_query.source_addr ==
457: route_query->source_addr) &&
458: (rc->route_query.dest_addr ==
459: route_query->dest_addr) &&
460: (!strcmp(rc->client_addr.sun_path,client_addr.sun_path))) {
461: /* Cache entry already exists.
462: * Check if route notification bit has been cleared.
463: */
464: if (!BIT_TST(rsrr->flags, RSRR_NOTIFICATION_BIT)) {
465: /* Delete cache entry. */
466: *rcnp = rc->next;
467: free(rc);
468: } else {
469: /* Update */
470: /* TODO: XXX: No need to update iif, oifs, flags */
471: rc->route_query.query_id = route_query->query_id;
472: IF_DEBUG(DEBUG_RSRR) {
473: logit(LOG_DEBUG, 0,
474: "Update cached query id %ld from client %s\n",
475: rc->route_query.query_id, rc->client_addr.sun_path);
476: }
477: }
478: return;
479: }
480: rcnp = &rc->next;
481: }
482:
483: /* Cache entry doesn't already exist. Create one and insert at
484: * front of list.
485: */
486: rc = (struct rsrr_cache *)calloc(1, sizeof(struct rsrr_cache));
487: if (rc == NULL)
488: logit(LOG_ERR, 0, "Ran out of memory in rsrr_cache()");
489:
490: rc->route_query.source_addr = route_query->source_addr;
491: rc->route_query.dest_addr = route_query->dest_addr;
492: rc->route_query.query_id = route_query->query_id;
493: strlcpy(rc->client_addr.sun_path, client_addr.sun_path, sizeof(rc->client_addr.sun_path));
494: rc->client_length = client_length;
495: #ifdef PIM
496: rc->next = gt->rsrr_cache;
497: gt->rsrr_cache = rc;
498: #else
499: rc->next = gt->gt_rsrr_cache;
500: gt->gt_rsrr_cache = rc;
501: #endif /* PIM */
502: IF_DEBUG(DEBUG_RSRR) {
503: logit(LOG_DEBUG, 0, "Cached query id %ld from client %s\n",
504: rc->route_query.query_id, rc->client_addr.sun_path);
505: }
506: }
507:
508: /* Send all the messages in the cache for particular routing entry.
509: * Currently this is used to send all the cached Route Reply messages
510: * for route change notification.
511: */
512: void rsrr_cache_send(struct gtable *gt, int notify)
513: {
514: struct rsrr_cache *rc, **rcnp;
515: uint8_t flags = 0;
516:
517: if (notify) {
518: BIT_SET(flags, RSRR_NOTIFICATION_BIT);
519: }
520:
521: #ifdef PIM
522: rcnp = >->rsrr_cache;
523: #else
524: rcnp = >->gt_rsrr_cache;
525: #endif /* PIM */
526:
527: while ((rc = *rcnp) != NULL) {
528: if (rsrr_accept_rq(&rc->route_query, flags, gt) < 0) {
529: IF_DEBUG(DEBUG_RSRR) {
530: logit(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n",
531: rc->route_query.query_id,rc->client_addr.sun_path);
532: }
533: /* Delete cache entry. */
534: *rcnp = rc->next;
535: free(rc);
536: } else {
537: rcnp = &rc->next;
538: }
539: }
540: }
541:
542: /* Bring "up" the RSRR cache entries: the (S,G) entry brings up any
543: * matching entry from (*,*,RP) or (*,G). The (*,G) entry brings up
544: * any matching entries from (*,*,RP)
545: */
546: void rsrr_cache_bring_up(struct gtable *gt)
547: {
548: struct gtable *gt_rp, *gt_wide;
549: uint8_t flags = 0;
550: struct rsrr_cache *rc, **rcnp;
551:
552: if (gt == (struct gtable *)NULL)
553: return;
554: if (gt->flags & MRTF_PMBR)
555: /* (*,*,RP) */
556: return;
557: if (gt->flags & MRTF_WC) {
558: /* (*,G) */
559: if (((gt_rp = gt->group->active_rp_grp->rp->rpentry->mrtlink) ==
560: (struct gtable *)NULL)
561: || (gt_rp->rsrr_cache == (struct rsrr_cache *)NULL))
562: return;
563: if ((gt_rp->incoming == gt->incoming)
564: && (VIFM_SAME(gt->oifs, gt_rp->oifs))) {
565: /* The (iif, oifs) are the same. Just link to the new routing
566: * table entry. No need to send message to rsvpd */
567: rcnp = >_rp->rsrr_cache;
568: while ((rc = *rcnp) != NULL) {
569: if (rc->route_query.dest_addr == gt->group->group) {
570: *rcnp = rc->next;
571: rc->next = gt->rsrr_cache;
572: gt->rsrr_cache = rc;
573: }
574: else {
575: rcnp = &rc->next;
576: }
577: }
578: }
579: else {
580: /* Have to move the entries and at the same time
581: * send an update message to rsvpd for each of them.
582: */
583: /* TODO: XXX: this can be done faster */
584: rcnp = >_rp->rsrr_cache;
585: BIT_SET(flags, RSRR_NOTIFICATION_BIT);
586: if (gt->group->mrtlink != (mrtentry_t *)NULL) {
587: RSRR_THIS_SENDER_SHARED_TREE_SOME_OTHER_NOT(flags);
588: }
589: else {
590: RSRR_SET_ALL_SENDERS_SHARED_TREE(flags);
591: }
592: while ((rc = *rcnp) != NULL) {
593: if (rc->route_query.dest_addr == gt->group->group) {
594: *rcnp = rc->next;
595: if (rsrr_accept_rq(&rc->route_query, flags, gt) < 0) {
596: IF_DEBUG(DEBUG_RSRR) {
597: logit(LOG_DEBUG, 0,
598: "Deleting cached query id %ld from client %s\n",
599: rc->route_query.query_id,
600: rc->client_addr.sun_path);
601: }
602: }
603: /* Even on success have to delete it. */
604: *rcnp = rc->next;
605: free(rc);
606: }
607: }
608: }
609: return;
610: } /* end of (*,G) */
611:
612: if (gt->flags & MRTF_SG) {
613: /* (S,G) */
614: /* Check first (*,*,RP) */
615: if (((gt_wide = gt->group->active_rp_grp->rp->rpentry->mrtlink) ==
616: (struct gtable *)NULL)
617: || (gt_wide->rsrr_cache == (struct rsrr_cache *)NULL)) {
618: if (((gt_wide = gt->group->grp_route) == (struct gtable *)NULL)
619: || (gt_wide->rsrr_cache == (struct rsrr_cache *)NULL))
620: return;
621: }
622: BIT_SET(flags, RSRR_NOTIFICATION_BIT);
623: try_again:
624: rcnp = >_wide->rsrr_cache;
625: while((rc = *rcnp) != NULL) {
626: if ((rc->route_query.dest_addr == gt->group->group)
627: && (rc->route_query.source_addr ==
628: gt->source->address)) {
629: /* Found it. Need just this entry */
630: *rcnp = rc->next; /* Free from the original chain */
631: if ((gt_wide->incoming == gt->incoming)
632: && (VIFM_SAME(gt_wide->oifs, gt->oifs))) {
633: /* The (iif, oifs) are the same. Just link to the
634: * new routing table entry. No need to send
635: * message to rsvpd
636: */
637: rc->next = gt->rsrr_cache;
638: gt->rsrr_cache = rc;
639: }
640: else {
641: /* The iif and/or oifs are different. Send a message
642: * to rsvpd
643: */
644: if (rsrr_accept_rq(&rc->route_query, flags, gt) < 0) {
645: IF_DEBUG(DEBUG_RSRR) {
646: logit(LOG_DEBUG, 0,
647: "Deleting cached query id %ld from client %s\n",
648: rc->route_query.query_id,
649: rc->client_addr.sun_path);
650: }
651: }
652: /* Even on success have to delete it. */
653: free(rc);
654: }
655: return;
656: }
657: }
658: if (gt_wide->flags & MRTF_PMBR) {
659: if (((gt_wide = gt->group->grp_route) == (struct gtable *)NULL)
660: || (gt_wide->rsrr_cache == (struct rsrr_cache *)NULL))
661: return;
662: goto try_again;
663: }
664: }
665: }
666:
667: /* Clean the cache by deleting or moving all entries. */
668: /* XXX: for PIM, if the routing entry is (S,G), will try first to
669: * "transfer" the RSRR cache entry to the (*,G) or (*,*,RP) routing entry
670: * (if any). If the current routing entry is (*,G), it will move the
671: * cache entries to the (*,*,RP) routing entry (if existing).
672: * If the old and the new (iif, oifs) are the same, then no need to send
673: * route change message to the reservation daemon: just plug all entries at
674: * the front of the rsrr_cache chain.
675: */
676: void rsrr_cache_clean(struct gtable *gt)
677: {
678: struct rsrr_cache *rc, *rc_next, **rcnp;
679: struct gtable *gt_wide;
680: #ifdef PIM
681: uint8_t flags = 0;
682:
683: IF_DEBUG(DEBUG_RSRR) {
684: if (gt->flags & MRTF_SG)
685: logit(LOG_DEBUG, 0, "cleaning cache for source %s and group %s",
686: inet_fmt(gt->source->address, s1, sizeof(s1)),
687: inet_fmt(gt->group->group, s2, sizeof(s2)));
688: else if (gt->flags & MRTF_WC)
689: logit(LOG_DEBUG, 0, "cleaning cache for group %s and ANY sources",
690: inet_fmt(gt->group->group, s1, sizeof(s1)));
691: else if (gt->flags & MRTF_PMBR)
692: logit(LOG_DEBUG, 0,
693: "cleaning cache for ALL groups matching to RP %s",
694: inet_fmt(gt->source->address, s1, sizeof(s1)));
695: }
696: rc = gt->rsrr_cache;
697: if (rc == (struct rsrr_cache *)NULL)
698: return;
699: if (gt->flags & MRTF_SG) {
700: if ((gt_wide = gt->group->grp_route) == (struct gtable *)NULL)
701: gt_wide = gt->group->active_rp_grp->rp->rpentry->mrtlink;
702: }
703: else if (gt->flags & MRTF_WC)
704: gt_wide = gt->group->active_rp_grp->rp->rpentry->mrtlink;
705: else
706: gt_wide = (struct gtable *)NULL;
707:
708: if (gt_wide == (struct gtable *)NULL) {
709: /* No routing entry where to move down the rsrr cache entry.
710: * Send a message with "cannot_notify" bit set.
711: */
712: rsrr_cache_send(gt, 0);
713: while (rc) {
714: rc_next = rc->next;
715: free(rc);
716: rc = rc_next;
717: }
718: } else if ((gt_wide->incoming == gt->incoming)
719: && (VIFM_SAME(gt->oifs, gt_wide->oifs))) {
720: /* The (iif, oifs) are the same. Just move to the beginning of the
721: * RSRR cache chain. No need to send message */
722: while (rc->next != (struct rsrr_cache *)NULL)
723: rc = rc->next;
724: rc->next = gt_wide->rsrr_cache;
725: gt_wide->rsrr_cache = gt->rsrr_cache;
726: }
727: else {
728: /* Have to move to the RSRR cache entries and at the same time
729: * send an update for each of them.
730: */
731: rcnp = >->rsrr_cache;
732: BIT_SET(flags, RSRR_NOTIFICATION_BIT);
733: if (gt->group->mrtlink != (mrtentry_t *)NULL) {
734: RSRR_THIS_SENDER_SHARED_TREE_SOME_OTHER_NOT(flags);
735: }
736: else {
737: RSRR_SET_ALL_SENDERS_SHARED_TREE(flags);
738: }
739: while ((rc = *rcnp) != NULL) {
740: if (rsrr_accept_rq(&rc->route_query, flags, gt_wide) < 0) {
741: IF_DEBUG(DEBUG_RSRR) {
742: logit(LOG_DEBUG, 0,
743: "Deleting cached query id %ld from client %s\n",
744: rc->route_query.query_id, rc->client_addr.sun_path);
745: }
746: /* Delete cache entry. */
747: *rcnp = rc->next;
748: free(rc);
749: } else {
750: rcnp = &rc->next;
751: }
752: }
753: }
754: gt->rsrr_cache = (struct rsrr_cache *)NULL;
755:
756: #else
757: IF_DEBUG(DEBUG_RSRR) {
758: logit(LOG_DEBUG, 0, "cleaning cache for group %s\n",
759: inet_fmt(gt->gt_mcastgrp, s1, sizeof(s1)));
760: }
761: rc = gt->gt_rsrr_cache;
762: while (rc) {
763: rc_next = rc->next;
764: free(rc);
765: rc = rc_next;
766: }
767: gt->gt_rsrr_cache = NULL;
768: #endif /* PIM */
769: }
770:
771: void rsrr_clean(void)
772: {
773: unlink(RSRR_SERV_PATH);
774: }
775:
776: #else /* !RSRR */
777: static int dummy __attribute__((unused));
778: #endif /* RSRR */
779:
780: /**
781: * Local Variables:
782: * version-control: t
783: * indent-tabs-mode: t
784: * c-file-style: "ellemtel"
785: * c-basic-offset: 4
786: * End:
787: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>