|
1 /* |
|
2 * Copyright 2004-2006 Intel Corporation |
|
3 * |
|
4 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 * you may not use this file except in compliance with the License. |
|
6 * You may obtain a copy of the License at |
|
7 * |
|
8 * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 * |
|
10 * Unless required by applicable law or agreed to in writing, software |
|
11 * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 * See the License for the specific language governing permissions and |
|
14 * limitations under the License. |
|
15 */ |
|
16 |
|
17 #ifndef _ETH_CONVERGENCE_LAYER_H_ |
|
18 #define _ETH_CONVERGENCE_LAYER_H_ |
|
19 |
|
20 // Only works on Linux (for now) |
|
21 #ifdef __linux__ |
|
22 |
|
23 #include <sys/types.h> |
|
24 #include <netinet/in.h> |
|
25 #include <linux/if.h> |
|
26 |
|
27 #include <oasys/thread/Thread.h> |
|
28 #include <oasys/thread/Timer.h> |
|
29 |
|
30 #include "ConvergenceLayer.h" |
|
31 #include "naming/EthernetScheme.h" // for eth_addr_t |
|
32 |
|
33 /** |
|
34 * The EthConvergenceLayer provides access to any ethernet interfaces that |
|
35 * support RAW sockets. It periodically sends beacons out on each interface |
|
36 * to support neighbor discovery. (this may change later). |
|
37 * |
|
38 * To add an ethernet interface in your config file, use: |
|
39 * |
|
40 * interface add eth string://eth0 |
|
41 * |
|
42 * Theoretically, any router type should work, but so far, the only one I've |
|
43 * been using is the NeighborhoodRouter. To use this router, add this to dtn.conf |
|
44 * |
|
45 * route set type neighborhood |
|
46 * |
|
47 */ |
|
48 namespace dtn { |
|
49 |
|
50 class EthConvergenceLayer : public ConvergenceLayer { |
|
51 |
|
52 public: |
|
53 class BeaconTimer; |
|
54 |
|
55 /** |
|
56 * Current version of the protocol. |
|
57 */ |
|
58 static const u_int8_t ETHCL_VERSION = 0x01; |
|
59 static const u_int16_t ETHERTYPE_DTN = 0xd710; |
|
60 |
|
61 static const u_int8_t ETHCL_BEACON = 0x01; |
|
62 static const u_int8_t ETHCL_BUNDLE = 0x02; |
|
63 |
|
64 static const u_int32_t ETHCL_BEACON_TIMEOUT_INTERVAL = 2500; // 2.5 seconds |
|
65 |
|
66 static const u_int16_t MAX_ETHER_PACKET = 1518; |
|
67 |
|
68 /** |
|
69 * Maximum bundle size |
|
70 */ |
|
71 static const u_int MAX_BUNDLE_LEN = 65507; |
|
72 |
|
73 /** |
|
74 * The basic Eth header structure. |
|
75 */ |
|
76 struct EthCLHeader { |
|
77 u_int8_t version; ///< ethcl protocol version |
|
78 u_int8_t type; ///< |
|
79 u_int16_t _padding2; ///< |
|
80 u_int32_t bundle_id; ///< bundle identifier at sender |
|
81 } __attribute__((packed)); |
|
82 |
|
83 /** |
|
84 * Data state of a Eth cl |
|
85 * |
|
86 */ |
|
87 class EthCLInfo : public CLInfo { |
|
88 public: |
|
89 EthCLInfo(char* if_name) { |
|
90 memset(if_name_,0,IFNAMSIZ); |
|
91 strcpy(if_name_,if_name); |
|
92 timer = NULL; |
|
93 } |
|
94 |
|
95 ~EthCLInfo() { |
|
96 if(timer) |
|
97 delete timer; |
|
98 } |
|
99 |
|
100 // Name of the device |
|
101 char if_name_[IFNAMSIZ]; |
|
102 |
|
103 BeaconTimer* timer; |
|
104 }; |
|
105 |
|
106 /** |
|
107 * Constructor. |
|
108 */ |
|
109 EthConvergenceLayer(); |
|
110 |
|
111 /** |
|
112 * Bring up a new interface. |
|
113 */ |
|
114 bool interface_up(Interface* iface, int argc, const char* argv[]); |
|
115 |
|
116 /** |
|
117 * Bring down the interface. |
|
118 */ |
|
119 bool interface_down(Interface* iface); |
|
120 |
|
121 /** |
|
122 * Open the connection to a given contact and send/listen for |
|
123 * bundles over this contact. |
|
124 */ |
|
125 bool open_contact(const ContactRef& contact); |
|
126 |
|
127 /** |
|
128 * Close the connnection to the contact. |
|
129 */ |
|
130 bool close_contact(const ContactRef& contact); |
|
131 |
|
132 /** |
|
133 * Delete any CL-specific components of the Link. |
|
134 */ |
|
135 void delete_link(const LinkRef& link); |
|
136 |
|
137 /** |
|
138 * Send the bundle to the contact |
|
139 */ |
|
140 void bundle_queued(const LinkRef& link, const BundleRef& bundle); |
|
141 |
|
142 /** |
|
143 * Report if the given bundle is queued on the given link. |
|
144 */ |
|
145 bool is_queued(const LinkRef& contact, Bundle* bundle); |
|
146 |
|
147 /** |
|
148 * Tunable parameter structure. |
|
149 * |
|
150 * Per-link and per-interface settings are configurable via |
|
151 * arguments to the 'link add' and 'interface add' commands. |
|
152 * |
|
153 * The parameters are stored in each Link's CLInfo slot, as well |
|
154 * as part of the Receiver helper class. |
|
155 */ |
|
156 class Params : public CLInfo { |
|
157 public: |
|
158 u_int32_t beacon_interval_; ///< Beacon Interval |
|
159 }; |
|
160 |
|
161 /** |
|
162 * Default parameters. |
|
163 */ |
|
164 static Params defaults_; |
|
165 |
|
166 /** |
|
167 * Helper class (and thread) that listens on a registered |
|
168 * interface for incoming data. |
|
169 */ |
|
170 class Receiver : public CLInfo, |
|
171 public oasys::Logger, |
|
172 public oasys::Thread |
|
173 { |
|
174 public: |
|
175 /** |
|
176 * Constructor. |
|
177 */ |
|
178 Receiver(const char *if_name, EthConvergenceLayer::Params* params); |
|
179 |
|
180 /** |
|
181 * Destructor. |
|
182 */ |
|
183 virtual ~Receiver() {} |
|
184 |
|
185 /** |
|
186 * Loop forever, issuing blocking calls to IPSocket::recvfrom(), |
|
187 * then calling the process_data function when new data does |
|
188 * arrive |
|
189 * |
|
190 * Note that unlike in the Thread base class, this run() method is |
|
191 * public in case we don't want to actually create a new thread |
|
192 * for this guy, but instead just want to run the main loop. |
|
193 */ |
|
194 void run(); |
|
195 |
|
196 protected: |
|
197 /** |
|
198 * Handler to process an arrived packet. |
|
199 */ |
|
200 void process_data(u_char* bp, size_t len); |
|
201 char if_name_[IFNAMSIZ]; |
|
202 }; |
|
203 |
|
204 |
|
205 |
|
206 /** |
|
207 * Helper class (and thread) that manages an "established" |
|
208 * connection with a peer daemon (virtual connection in the |
|
209 * case of Eth). |
|
210 * |
|
211 * Only the sender side of the connection needs to initiate |
|
212 * a connection. The receiver will just receive data. Therefore, |
|
213 * we don't need a passive side of a connection |
|
214 */ |
|
215 class Sender : public CLInfo, |
|
216 public oasys::Logger |
|
217 { |
|
218 public: |
|
219 /** |
|
220 * Constructor for the active connection side of a connection. |
|
221 */ |
|
222 Sender(char* if_name, const ContactRef& contact); |
|
223 |
|
224 /** |
|
225 * Destructor. |
|
226 */ |
|
227 virtual ~Sender() {} |
|
228 |
|
229 protected: |
|
230 friend class EthConvergenceLayer; |
|
231 |
|
232 /** |
|
233 * Send one bundle. |
|
234 */ |
|
235 bool send_bundle(const BundleRef& bundle); |
|
236 |
|
237 /// The contact that we're representing |
|
238 ContactRef contact_; |
|
239 |
|
240 /// Socket identifier |
|
241 int sock_; |
|
242 |
|
243 /// MAC address of the interface used for this contact |
|
244 eth_addr_t src_hw_addr_; |
|
245 eth_addr_t dst_hw_addr_; |
|
246 |
|
247 /// The name of the interface the next_hop is behind |
|
248 char if_name_[IFNAMSIZ]; |
|
249 |
|
250 char canary_[7]; |
|
251 |
|
252 /** |
|
253 * Temporary buffer for formatting bundles. Note that the |
|
254 * fixed-length buffer is big enough since UDP packets can't |
|
255 * be any bigger than that. |
|
256 */ |
|
257 u_char buf_[EthConvergenceLayer::MAX_BUNDLE_LEN]; |
|
258 }; |
|
259 |
|
260 /** |
|
261 * helper class (and thread) that periodically sends beacon messages |
|
262 * over the specified ethernet interface. |
|
263 */ |
|
264 class Beacon : public oasys::Logger, |
|
265 public oasys::Thread |
|
266 { |
|
267 public: |
|
268 Beacon(const char* if_name, unsigned int beacon_interval); |
|
269 |
|
270 virtual ~Beacon() {}; |
|
271 |
|
272 private: |
|
273 virtual void run(); |
|
274 char if_name_[IFNAMSIZ]; |
|
275 unsigned int beacon_interval_; |
|
276 }; |
|
277 |
|
278 class BeaconTimer : public oasys::Logger, public oasys::Timer, public CLInfo { |
|
279 public: |
|
280 char * next_hop_; |
|
281 |
|
282 BeaconTimer(char * next_hop); |
|
283 ~BeaconTimer(); |
|
284 |
|
285 void timeout(const struct timeval& now); |
|
286 |
|
287 Timer* copy(); |
|
288 }; |
|
289 |
|
290 protected: |
|
291 /** |
|
292 * Parses parameters during EthConvegenceLayer initialization |
|
293 */ |
|
294 bool parse_params(Params* params, int argc, const char** argv, |
|
295 const char** invalidp); |
|
296 |
|
297 private: |
|
298 Beacon *if_beacon_; |
|
299 }; |
|
300 |
|
301 |
|
302 } // namespace dtn |
|
303 |
|
304 #endif // __linux |
|
305 |
|
306 #endif /* _ETH_CONVERGENCE_LAYER_H_ */ |