1 /*
2 *
3 * Copyright (c) 2003 The Regents of the University of California. All
4 * 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 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Neither the name of the University nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <ctype.h>
36 #include <sys/time.h>
37 #include <arpa/inet.h>
38 #include <math.h>
39
40 #include "emrun/emrun.h"
41 #include "link/link.h"
42 #include <link/link_headers.h>
43 #include <libmisc/misc.h>
44 #include <libdev/status_dev.h>
45 #include <libdev/command_dev.h>
46 #include <libdev/query_dev.h>
47 #include <libdev/packet_client.h>
48 #include <libdev/packet_dev.h>
49 #include <libdev/em_sched.h>
50 #include <dsr_i.h>
51 #include <routing/routing_table.h>
52 #include <libdev/command_dev.h>
53 #include <devel/state/ssync.h>
54
55
56 int dsr_upper_send(lp_context_t *lp, link_pkt_t *pkt, int datalen,
57 int loop_needed);
58 int dsr_upper_status(lp_context_t *lp);
59 int dsr_upper_ioctl(lp_context_t *lp, int cmd, void *arg);
60 int dsr_upper_parse_commands(lp_context_t *lp, parser_state_t *cmd_input);
61 void dsr_upper_usage(lp_context_t *lp, buf_t *buf);
62 int dsr_upper_enqueue(lp_context_t *lp, link_pkt_t *pkt, int datalen);
63
64 int flush_timer_expired(void *data, int interval, g_event_t *ev)
65 {
66 dsr_rtable_entry_t *rtentry = (dsr_rtable_entry_t *)(data);
67
68 if (rtentry->flush_pending == 1) {
69 flush_pkt_queue(rtentry);
70 }
71 rtentry->flush_pending = 0;
72
73 return TIMER_DONE;
74 }
75
76
77
78 int dsr_upper_enqueue(lp_context_t *lp, link_pkt_t *pkt, int datalen)
79 {
80 dsr_state_t *dstate = (dsr_state_t *)lp_data(lp);
81 dsr_rtable_entry_t *rtentry=NULL;
82
83 // if we're off, return EAGAIN at once
84 if (dstate->cmd_status == STATE_OFF) {
85 return -EAGAIN;
86 }
87
88 if (pkt->dst.id == LINK_BROADCAST) {
89 // We don't support broadcasts for now
90 elog(LOG_ERR, "Broadcast destination not supported yet!!!");
91 return -EDESTADDRREQ;
92 }
93
94 rtentry = find_routing_table_entry_for_destination(pkt->dst.id, dstate);
95
96 if (rtentry == NULL) {
97 goto done;
98 }
99
100
101 // if ((rtentry->status != ENTRY_PATH_EXISTS) &&
102 if (pending_pkts_list_qlen(rtentry) >
103 dstate->max_pending_pkt_queue_size) {
104 // path doesn't exist and queue is full!
105 elog(LOG_ERR, "Cant enqueue pkt, internal destination (%d)"
106 " queue full", rtentry->dst);
107
108 // I should really start a timer and if the queue is full when it
109 // expires, THEN flush it
110 if (g_timer_isset(rtentry->flush_timer)==0) {
111 g_timer_add(dstate->flush_timeout_sec, flush_timer_expired,
112 rtentry, NULL, &(rtentry->flush_timer));
113 }
114 rtentry->flush_pending = 1;
115
116 return -EAGAIN;
117 }
118
119 done:
120 return 0;
121 }
122
123
124
125 int dsr_upper_send(lp_context_t *lp, link_pkt_t *pkt, int datalen,
126 int loop_needed)
127 {
128 dsr_state_t *dstate = (dsr_state_t *)lp_data(lp);
129 dsr_rtable_entry_t *rtentry=NULL;
130 int retval = 0;
131 int block = 0;
132 link_pkt_t *link_pkt = (link_pkt_t *)pkt;
133
134 // XXX XXX XXX
135 // WE ASSUME THAT THE USER OF UPPER USES NODE_IDS NOT IF_IDS!!!
136
137 if (pkt->dst.id == my_node_id) {
138 // if I am sending a pkt to myself, immediately deliver it upwards
139 lp_receive(lp, pkt, datalen);
140 goto done;
141 }
142
143 rtentry = find_routing_table_entry_for_destination(pkt->dst.id, dstate);
144
145 if (rtentry==NULL) {
146 // destination doesn't exist in our table, create it
147 rtentry = create_rtable_entry(pkt->dst.id, dstate);
148 if (rtentry==NULL) {
149 elog(LOG_ERR, "Could not create routing table entry!");
150 exit(1);
151 }
152 }
153
154 // rtentry is valid
155 //
156 // check if we have a valid path to that destination
157 if (path_exists(rtentry) == 0) {
158 // path is invalid
159 //
160 // 1. Enqueue the packet in rtentry's queue
161 // 2. *MAYBE* send RREQ (based on our rreq rate limiting timer)
162 //
163 enqueue_pending_pkt(pkt, datalen, rtentry);
164 maybe_send_rreq(rtentry, dstate);
165 block = 0;
166 goto done;
167
168 } else {
169 // send the pkt to the lower interface
170 // this function will take care of header settings, table lookups
171 // etc
172 retval = send_pkt_to_lower(pkt, datalen, rtentry, dstate);
173 block = 1;
174 }
175
176 done:
177 if (loop_needed) {
178 link_pkt->src.id = my_node_id;
179 lp_loop_receive(lp, link_pkt, datalen);
180 }
181
182 //if we ended up calling send_to_lower, block
183 if (block) {
184 return LP_BLOCKED;
185 } else {
186 return 0;
187 }
188 }
189
190
191
192 int dsr_upper_status(lp_context_t *lp)
193 {
194 return EVENT_RENEW;
195 }
196
197
198 int dsr_upper_ioctl(lp_context_t *lp, int cmd, void *arg)
199 {
200 return 0;
201 }
202
203
204 int dsr_upper_parse_commands(lp_context_t *lp, parser_state_t *cmd_input)
205 {
206 return 0;
207 }
208
209
210 void dsr_upper_usage(lp_context_t *lp, buf_t *buf)
211 {
212 }
213
214
215
216
217
218
219 void dsr_init_upper(dsr_state_t *dstate)
220 {
221 lp_opts_t opts = {
222 description: "DSR routing interface",
223 opts: {
224 name: dstate->link_provides_name,
225 if_class: dstate->class_name,
226 //if_class: LINK_CLASS_ROUTING,
227 data: dstate,
228 },
229
230
231 initial_status : {
232 // TODO: fix the mtu!
233 MTU: dstate->provided_mtu,
234 if_id: my_node_id,
235 },
236
237 send: dsr_upper_send,
238 enqueue: dsr_upper_enqueue,
239 status_request: dsr_upper_status,
240 ioctl: dsr_upper_ioctl,
241 command_request: dsr_upper_parse_commands,
242 usage: dsr_upper_usage,
243
244 we_are_root:1
245 };
246
247 if (lp_register(&opts, &(dstate->provided_link)) < 0) {
248 elog(LOG_CRIT, "Can't create link device %s: %m",
249 link_name(&opts.opts, NULL));
250 exit(1);
251 } else {
252 elog(LOG_NOTICE, "Link device %s created",
253 link_name(&opts.opts, NULL));
254 }
255
256 }
257
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.