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
33 #include "common.h"
34 #include "gls_i.h"
35 #include "hash.h"
36 #include "dijkstra.h"
37
38 extern node_id_t my_node_id;
39 extern loc_t my_loc;
40
41 #define MY_LOG_LEVEL LOG_DEBUG(4)
42
43 static void gls_upcall_to_user (gls_state_t *gls_state, ssize_t data_len, link_pkt_t *link_pkt_in)
44 {
45 /* Get the gls packet from link packet */
46 gls_pkt_t *gls_pkt_in = (gls_pkt_t *) link_pkt_in->data;
47
48 link_pkt_t up_link_hdr = {
49 src: {
50 loc: {
51 x: loc_expand(gls_pkt_in->original_src.addr.geo.x), /* set src to original src location */
52 y: loc_expand(gls_pkt_in->original_src.addr.geo.y),
53 },
54 },
55 dst: {
56 loc: {
57 x: loc_expand(gls_pkt_in->final_dst.addr.geo.x), /* set dst to the final dst loc */
58 y: loc_expand(gls_pkt_in->final_dst.addr.geo.y),
59 },
60 },
61 type: gls_pkt_in->inner_type, /* set type to application type */
62 };
63
64 buf_t *up_pkt = buf_new();
65
66 elog (LOG_DEBUG_0, "Upcall to user");
67
68 /* first construct the link header */
69 bufcpy(up_pkt, &up_link_hdr, sizeof(up_link_hdr));
70
71 /* the gls header has been stripped out, so only copy user data */
72
73 /* followed by user data */
74 bufcpy(up_pkt, gls_pkt_in->data, data_len - sizeof(gls_pkt_t));
75
76 /* For debugging. Spit out packet contents */
77 elog(MY_LOG_LEVEL, "Printing Packet: Datalen:%d glspktsize:%d link_hdr:%d",
78 data_len,sizeof(gls_pkt_t), sizeof(link_pkt_in));
79 elog_raw(MY_LOG_LEVEL, gls_pkt_in->data, data_len - sizeof(gls_pkt_t));
80 elog(MY_LOG_LEVEL, "Full Packet");
81 elog_raw(MY_LOG_LEVEL, link_pkt_in->data, data_len);
82
83 /* send it up */
84 pd_receive(gls_state->pd_context, up_pkt->buf, up_pkt->len);
85
86 /* free the buffer that we created */
87 buf_free(up_pkt);
88 }
89
90 /*
91 * This callback is called whenever a packet arrives up from one of
92 * the underlying datalink interfaces
93 */
94 static int gls_receiver(link_pkt_t *link_pkt_in, ssize_t data_len, link_context_t *link)
95 {
96 /* Get out state pointer */
97 gls_state_t *gls_state = (gls_state_t *) link_opts(link)->data;
98 /* Get the gls packet from link packet */
99 gls_pkt_t *gls_pkt_in = (gls_pkt_t *) link_pkt_in->data;
100
101 /* address/location to be looked up */
102 /* assume that input address is geographic */
103 gls_addr_t gls_addr_in = {
104 addr: {
105 geo: gls_pkt_in->final_dst.addr.geo,
106 },
107 type: ADDR_GEO,
108 };
109 /* address after lookup */
110 gls_addr_t gls_addr_out;
111 /* result of lookup */
112 gboolean lookup_result=FALSE;
113
114 elog(LOG_NOTICE, "RECEIVE DATA SIZE: %d", data_len);
115
116 elog (MY_LOG_LEVEL, "got packet OrigSrc:%2.2f,%2.2f FinalDst:%2.2f,%2.2f",
117 loc_expand(gls_pkt_in->original_src.addr.geo.x),
118 loc_expand(gls_pkt_in->original_src.addr.geo.y),
119 loc_expand(gls_pkt_in->final_dst.addr.geo.x),
120 loc_expand(gls_pkt_in->final_dst.addr.geo.y));
121
122 /*
123 * Make sure the packet has the right packet type. Since we
124 * specified the desired packet type when we registered to receive
125 * packets, this test should never fail.
126 */
127 if (link_pkt_in->type != PKT_TYPE_GLS) {
128 elog(LOG_WARNING, "got a packet not meant for us - filter failed!");
129 goto done;
130 }
131
132 /*
133 * Make sure the data portion of the packet is at least the size of
134 * a gls header
135 */
136 if (data_len < sizeof(gls_pkt_t)) {
137 elog(LOG_ERR, "got a short gls packet (%d bytes < %d)!", data_len,
138 sizeof(gls_pkt_t));
139 goto done;
140 }
141
142 /* We want nodeid output, so set output type to nodeid */
143 gls_addr_out.type = ADDR_NODEID;
144
145 /* Lookup next hop to dst */
146 get_nexthop_to_dest_loc(&gls_addr_in, &gls_addr_out,
147 &lookup_result, gls_state->info);
148
149 /* drop pkt if no route to dst can be found */
150 /* XXX: Remember to free packet */
151 if (!lookup_result) goto done;
152
153 /* Send it up the stack if we are the
154 * node closest to destination location */
155 /* if (gls_addr_out.addr.nodeid == my_node_id) { */
156 /* goto done; */
157 /* } */
158
159 /* Decrement ttl; throw it away if it has hit zero */
160 /* if (--(gls_pkt_in->ttl) <= 0) */
161 /* goto done; */
162
163 if ((node_id_t)gls_addr_out.addr.nodeid == my_node_id) {
164 elog (MY_LOG_LEVEL, "Upcall: OrigSrc:%2.2f,%2.2f FinalDst:%2.2f,%2.2f",
165 loc_expand(gls_pkt_in->original_src.addr.geo.x),
166 loc_expand(gls_pkt_in->original_src.addr.geo.y),
167 loc_expand(gls_pkt_in->final_dst.addr.geo.x),
168 loc_expand(gls_pkt_in->final_dst.addr.geo.y));
169 }
170
171 /* forward received pkt to next_hop. Size of packet is unchanged */
172 gls_forward(gls_state, link_pkt_in,
173 data_len, (node_id_t)gls_addr_out.addr.nodeid);
174
175 done:
176 free(link_pkt_in);
177 return EVENT_RENEW;
178 }
179
180
181 /*
182 * This function opens one of the underlying transport devices used by
183 * the gls daemon (e.g., a basic datalink such as motenic)
184 * XXX: Use only once?
185 */
186 void gls_open_link(gls_state_t *g, int link_index)
187 {
188 gls_iface_t *i;
189
190 /* get a pointer to the next available iface struct */
191 i = &(g->iface);
192
193 /* set options for this link */
194 memset(i, 0, sizeof(gls_iface_t));
195 i->if_opts.link_index = link_index;
196 i->if_opts.pkt_type = PKT_TYPE_GLS;
197 i->if_opts.q_opts.outq_len = 1000;
198 i->if_opts.q_opts.inq_len = 1000;
199 i->if_opts.receive = gls_receiver;
200 i->if_opts.data = g;
201
202 /* try to open it */
203 if (link_open(&i->if_opts, &i->if_context) < 0) {
204 elog(LOG_CRIT, "can't open %s: %m", link_name(&i->if_opts));
205 exit(1);
206 }
207
208 /* Open succeeded - increment interface count */
209 elog(LOG_NOTICE, "opened lower interface: %s",link_name(&i->if_opts));
210 }
211
212
213 /*
214 * Send a link_pkt to all interfaces opened by the function above
215 */
216 void gls_forward (gls_state_t *gls_state, link_pkt_t *pkt,
217 ssize_t data_len, node_id_t next_hop)
218 {
219 int i;
220 if_id_t if_out; /* output interface */
221
222 /* Check if we are the next hop. If so, pass packet up and return */
223 if (next_hop == my_node_id) {
224 gls_upcall_to_user (gls_state, data_len, pkt);
225 return;
226 }
227
228 /* Find interface that next_hop corresponds to */
229 /* XXX: remove copy of interface */
230 for (i = 0; i < gls_state->nb_list_count; i++)
231 if (gls_state->nb_list[i].node_id == next_hop) {
232 if_out = gls_state->nb_list[i].if_id;
233 break;
234 }
235
236 elog(LOG_NOTICE, "TRANSMIT DATA SIZE: %d", data_len);
237
238 /* set the dst interface id to the neighbor's if_id */
239 pkt->dst.id = if_out;
240
241 elog(MY_LOG_LEVEL, "sending to %s", link_name(link_opts(gls_state->iface.if_context)));
242
243 if (link_send(gls_state->iface.if_context, pkt, data_len) < 0)
244 elog(LOG_WARNING, "sending to %s: %m", link_name(&(gls_state->iface.if_opts)));
245 }
246
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.