Annotation of embedaddon/quagga/ripngd/ripng_nexthop.c, revision 1.1.1.1
1.1 misho 1: /* RIPngd Zebra
2: * Copyright (C) 2002 6WIND <vincent.jardin@6wind.com>
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
17: * along with GNU Zebra; see the file COPYING. If not, write to the Free
18: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19: * 02111-1307, USA.
20: */
21:
22: /* This file is required in order to support properly the RIPng nexthop
23: * feature.
24: */
25:
26: #include <zebra.h>
27:
28: /* For struct udphdr. */
29: #include <netinet/udp.h>
30:
31: #include "linklist.h"
32: #include "stream.h"
33: #include "log.h"
34: #include "memory.h"
35: #include "vty.h"
36: #include "if.h"
37: #include "prefix.h"
38:
39: #include "ripngd/ripngd.h"
40: #include "ripngd/ripng_debug.h"
41: #include "ripngd/ripng_nexthop.h"
42:
43: #define DEBUG 1
44:
45: #define min(a, b) ((a) < (b) ? (a) : (b))
46:
47: struct ripng_rte_data {
48: struct prefix_ipv6 *p;
49: struct ripng_info *rinfo;
50: struct ripng_aggregate *aggregate;
51: };
52:
53: void _ripng_rte_del(struct ripng_rte_data *A);
54: int _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B);
55:
56: #define METRIC_OUT(a) \
57: ((a)->rinfo ? (a)->rinfo->metric_out : (a)->aggregate->metric_out)
58: #define NEXTHOP_OUT_PTR(a) \
59: ((a)->rinfo ? &((a)->rinfo->nexthop_out) : &((a)->aggregate->nexthop_out))
60: #define TAG_OUT(a) \
61: ((a)->rinfo ? (a)->rinfo->tag_out : (a)->aggregate->tag_out)
62:
63: struct list *
64: ripng_rte_new(void) {
65: struct list *rte;
66:
67: rte = list_new();
68: rte->cmp = (int (*)(void *, void *)) _ripng_rte_cmp;
69: rte->del = (void (*)(void *)) _ripng_rte_del;
70:
71: return rte;
72: }
73:
74: void
75: ripng_rte_free(struct list *ripng_rte_list) {
76: list_delete(ripng_rte_list);
77: }
78:
79: /* Delete RTE */
80: void
81: _ripng_rte_del(struct ripng_rte_data *A) {
82: XFREE(MTYPE_RIPNG_RTE_DATA, A);
83: }
84:
85: /* Compare RTE:
86: * return + if A > B
87: * 0 if A = B
88: * - if A < B
89: */
90: int
91: _ripng_rte_cmp(struct ripng_rte_data *A, struct ripng_rte_data *B) {
92: return addr6_cmp(NEXTHOP_OUT_PTR(A), NEXTHOP_OUT_PTR(B));
93: }
94:
95: /* Add routing table entry */
96: void
97: ripng_rte_add(struct list *ripng_rte_list, struct prefix_ipv6 *p,
98: struct ripng_info *rinfo, struct ripng_aggregate *aggregate) {
99:
100: struct ripng_rte_data *data;
101:
102: /* At least one should not be null */
103: assert(!rinfo || !aggregate);
104:
105: data = XMALLOC(MTYPE_RIPNG_RTE_DATA, sizeof(*data));
106: data->p = p;
107: data->rinfo = rinfo;
108: data->aggregate = aggregate;
109:
110: listnode_add_sort(ripng_rte_list, data);
111: }
112:
113: /* Send the RTE with the nexthop support
114: */
115: void
116: ripng_rte_send(struct list *ripng_rte_list, struct interface *ifp,
117: struct sockaddr_in6 *to) {
118:
119: struct ripng_rte_data *data;
120: struct listnode *node, *nnode;
121:
122: struct in6_addr last_nexthop;
123: struct in6_addr myself_nexthop;
124:
125: struct stream *s;
126: int num;
127: int mtu;
128: int rtemax;
129: int ret;
130:
131: /* Most of the time, there is no nexthop */
132: memset(&last_nexthop, 0, sizeof(last_nexthop));
133:
134: /* Use myself_nexthop if the nexthop is not a link-local address, because
135: * we remain a right path without beeing the optimal one.
136: */
137: memset(&myself_nexthop, 0, sizeof(myself_nexthop));
138:
139: /* Output stream get from ripng structre. XXX this should be
140: interface structure. */
141: s = ripng->obuf;
142:
143: /* Reset stream and RTE counter. */
144: stream_reset (s);
145: num = 0;
146:
147: mtu = ifp->mtu6;
148: if (mtu < 0)
149: mtu = IFMINMTU;
150:
151: rtemax = (min (mtu, RIPNG_MAX_PACKET_SIZE) -
152: IPV6_HDRLEN -
153: sizeof (struct udphdr) -
154: sizeof (struct ripng_packet) +
155: sizeof (struct rte)) / sizeof (struct rte);
156:
157: for (ALL_LIST_ELEMENTS (ripng_rte_list, node, nnode, data)) {
158: /* (2.1) Next hop support */
159: if (!IPV6_ADDR_SAME(&last_nexthop, NEXTHOP_OUT_PTR(data))) {
160:
161: /* A nexthop entry should be at least followed by 1 RTE */
162: if (num == (rtemax-1)) {
163: ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
164: to, ifp);
165:
166: if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
167: ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
168: stream_get_endp(s), "SEND");
169: num = 0;
170: stream_reset (s);
171: }
172:
173: /* Add the nexthop (2.1) */
174:
175: /* If the received next hop address is not a link-local address,
176: * it should be treated as 0:0:0:0:0:0:0:0.
177: */
178: if (!IN6_IS_ADDR_LINKLOCAL(NEXTHOP_OUT_PTR(data)))
179: last_nexthop = myself_nexthop;
180: else
181: last_nexthop = *NEXTHOP_OUT_PTR(data);
182:
183: num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
184: } else {
185: /* Rewrite the nexthop for each new packet */
186: if ((num == 0) && !IPV6_ADDR_SAME(&last_nexthop, &myself_nexthop))
187: num = ripng_write_rte(num, s, NULL, &last_nexthop, 0, RIPNG_METRIC_NEXTHOP);
188: }
189: num = ripng_write_rte(num, s, data->p, NULL,
190: TAG_OUT(data), METRIC_OUT(data));
191:
192: if (num == rtemax) {
193: ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
194: to, ifp);
195:
196: if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
197: ripng_packet_dump((struct ripng_packet *)STREAM_DATA (s),
198: stream_get_endp(s), "SEND");
199: num = 0;
200: stream_reset (s);
201: }
202: }
203:
204: /* If unwritten RTE exist, flush it. */
205: if (num != 0) {
206: ret = ripng_send_packet ((caddr_t) STREAM_DATA (s), stream_get_endp (s),
207: to, ifp);
208:
209: if (ret >= 0 && IS_RIPNG_DEBUG_SEND)
210: ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),
211: stream_get_endp (s), "SEND");
212: num = 0;
213: stream_reset (s);
214: }
215: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>