ia64/xen-unstable

view tools/vnet/vnet-module/etherip.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 06d84bf87159
children 71b0f00f6344
line source
1 /*
2 * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free software Foundation, Inc.,
16 * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19 #include <linux/config.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/kernel.h>
23 #include <linux/init.h>
25 #include <linux/version.h>
27 #include <linux/skbuff.h>
28 #include <linux/net.h>
29 #include <linux/netdevice.h>
30 #include <linux/in.h>
31 #include <linux/inet.h>
32 #include <linux/netfilter_ipv4.h>
33 #include <linux/icmp.h>
35 #include <net/ip.h>
36 #include <net/protocol.h>
37 #include <net/route.h>
38 #include <net/checksum.h>
40 #include <etherip.h>
41 #include <tunnel.h>
42 #include <vnet.h>
43 #include <varp.h>
44 #include <if_varp.h>
45 #include <varp.h>
46 #include <skb_util.h>
48 #define MODULE_NAME "VNET"
49 //#define DEBUG 1
50 #undef DEBUG
51 #include "debug.h"
53 /** @file Etherip implementation.
54 * The etherip protocol is used to transport Ethernet frames in IP packets.
55 */
57 /** Get the vnet label from an etherip header.
58 *
59 * @param hdr header
60 * @@param vnet (in net order)
61 */
62 void etheriphdr_get_vnet(struct etheriphdr *hdr, VnetId *vnet){
63 #ifdef CONFIG_ETHERIP_EXT
64 *vnet = *(VnetId*)hdr->vnet;
65 #else
66 *vnet = (VnetId){};
67 vnet->u.vnet16[7] = (unsigned short)hdr->reserved;
69 #endif
70 }
72 /** Set the vnet label in an etherip header.
73 * Also sets the etherip version.
74 *
75 * @param hdr header
76 * @param vnet vnet label (in net order)
77 */
78 void etheriphdr_set_vnet(struct etheriphdr *hdr, VnetId *vnet){
79 #ifdef CONFIG_ETHERIP_EXT
80 hdr->version = ETHERIP_VERSION;
81 *(VnetId*)hdr->vnet = *vnet;
82 #else
83 hdr->version = ETHERIP_VERSION;
84 hdr->reserved = (vnet->u.vnet16[7] & 0x0fff);
85 #endif
86 }
88 /** Open an etherip tunnel.
89 *
90 * @param tunnel to open
91 * @return 0 on success, error code otherwise
92 */
93 static int etherip_tunnel_open(Tunnel *tunnel){
94 return 0;
95 }
97 /** Close an etherip tunnel.
98 *
99 * @param tunnel to close
100 */
101 static void etherip_tunnel_close(Tunnel *tunnel){
102 }
105 /** Send a packet via an etherip tunnel.
106 * Adds etherip header, new ip header, new ethernet header around
107 * ethernet frame.
108 *
109 * @param tunnel tunnel
110 * @param skb packet
111 * @return 0 on success, error code otherwise
112 */
113 static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
114 int err = 0;
115 const int etherip_n = sizeof(struct etheriphdr);
116 const int ip_n = sizeof(struct iphdr);
117 const int eth_n = ETH_HLEN;
118 int head_n = 0;
119 VnetId *vnet = &tunnel->key.vnet;
120 struct etheriphdr *etheriph;
121 struct ethhdr *ethh;
122 u32 saddr = 0;
124 //dprintf("> skb=%p vnet=%d\n", skb, vnet);
125 head_n = etherip_n + ip_n + eth_n;
126 err = skb_make_room(&skb, skb, head_n, 0);
127 if(err) goto exit;
129 //err = vnet_get_device_address(skb->dev, &saddr);
130 //if(err) goto exit;
132 // The original ethernet header.
133 ethh = eth_hdr(skb);
134 //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len);
135 // Null the pointer as we are pushing a new IP header.
136 skb->mac.raw = NULL;
138 // Setup the etherip header.
139 //dprintf("> push etherip header...\n");
140 etheriph = (struct etheriphdr *)skb_push(skb, etherip_n);
141 etheriphdr_set_vnet(etheriph, vnet);
143 // Setup the IP header.
144 //dprintf("> push IP header...\n");
145 skb->nh.raw = skb_push(skb, ip_n);
146 skb->nh.iph->version = 4; // Standard version.
147 skb->nh.iph->ihl = ip_n / 4; // IP header length (32-bit words).
148 skb->nh.iph->tos = 0; // No special type-of-service.
149 skb->nh.iph->tot_len = htons(skb->len); // Total packet length (bytes).
150 skb->nh.iph->id = 0; // No flow id (since no frags).
151 skb->nh.iph->frag_off = htons(IP_DF); // Don't fragment - can't handle frags.
152 skb->nh.iph->ttl = 64; // Linux default time-to-live.
153 skb->nh.iph->protocol = IPPROTO_ETHERIP; // IP protocol number.
154 skb->nh.iph->saddr = saddr; // Source address.
155 skb->nh.iph->daddr = tunnel->key.addr.u.ip4.s_addr; // Destination address.
156 skb->nh.iph->check = 0;
158 // Ethernet header will be filled-in by device.
159 err = Tunnel_send(tunnel->base, skb);
160 skb = NULL;
161 exit:
162 if(err && skb) dev_kfree_skb(skb);
163 //dprintf("< err=%d\n", err);
164 return err;
165 }
167 /** Tunnel type for etherip.
168 */
169 static TunnelType _etherip_tunnel_type = {
170 .name = "ETHERIP",
171 .open = etherip_tunnel_open,
172 .close = etherip_tunnel_close,
173 .send = etherip_tunnel_send
174 };
176 TunnelType *etherip_tunnel_type = &_etherip_tunnel_type;
178 /* Defeat compiler warnings about unused functions. */
179 static void print_str(char *s, int n) __attribute__((unused));
181 static void print_str(char *s, int n) {
182 int i;
184 for(i=0; i<n; s++, i++){
185 if(i && i % 40 == 0) printk("\n");
186 if(('a'<= *s && *s <= 'z') ||
187 ('A'<= *s && *s <= 'Z') ||
188 ('0'<= *s && *s <= '9')){
189 printk("%c", *s);
190 } else {
191 printk("<%x>", (unsigned)(0xff & *s));
192 }
193 }
194 printk("\n");
195 }
197 /** Do etherip receive processing.
198 * Strips etherip header to extract the ethernet frame, sets
199 * the vnet from the header and re-receives the frame.
200 *
201 * @param skb packet
202 * @return 0 on success, error code otherwise
203 */
204 static int etherip_protocol_recv(struct sk_buff *skb){
205 int err = 0;
206 int mine = 0;
207 const int eth_n = ETH_HLEN;
208 int ip_n;
209 const int etherip_n = sizeof(struct etheriphdr);
210 struct etheriphdr *etheriph;
211 struct ethhdr *ethhdr;
212 Vnet *vinfo = NULL;
213 VnetId vnet = {};
214 u32 saddr, daddr;
215 char vnetbuf[VNET_ID_BUF];
217 saddr = skb->nh.iph->saddr;
218 daddr = skb->nh.iph->daddr;
219 ethhdr = eth_hdr(skb);
220 if(MULTICAST(daddr) && (daddr != varp_mcast_addr)){
221 // Ignore multicast packets not addressed to us.
222 dprintf("> Ignoring mcast skb: src=%u.%u.%u.%u dst=%u.%u.%u.%u"
223 " varp_mcast_addr=%u.%u.%u.%u\n",
224 NIPQUAD(saddr), NIPQUAD(daddr), NIPQUAD(varp_mcast_addr));
225 goto exit;
226 }
227 ip_n = (skb->nh.iph->ihl << 2);
228 if(skb->data == skb->mac.raw){
229 // skb->data points at ethernet header.
230 //dprintf("> len=%d\n", skb->len);
231 if (!pskb_may_pull(skb, eth_n + ip_n)){
232 wprintf("> Malformed skb (eth+ip) src=%u.%u.%u.%u\n",
233 NIPQUAD(saddr));
234 err = -EINVAL;
235 goto exit;
236 }
237 skb_pull(skb, eth_n + ip_n);
238 }
239 // Assume skb->data points at etherip header.
240 etheriph = (void*)skb->data;
241 if(etheriph->version != ETHERIP_VERSION){
242 wprintf("> Bad etherip version=%d src=%u.%u.%u.%u\n",
243 etheriph->version,
244 NIPQUAD(saddr));
245 err = -EINVAL;
246 goto exit;
247 }
248 if(!pskb_may_pull(skb, etherip_n)){
249 wprintf("> Malformed skb (etherip) src=%u.%u.%u.%u\n",
250 NIPQUAD(saddr));
251 err = -EINVAL;
252 goto exit;
253 }
254 etheriphdr_get_vnet(etheriph, &vnet);
255 dprintf("> Rcvd skb vnet=%s src=%u.%u.%u.%u\n",
256 VnetId_ntoa(&vnet, vnetbuf),
257 NIPQUAD(saddr));
258 // If vnet is secure, context must include IPSEC ESP.
259 err = vnet_check_context(&vnet, SKB_CONTEXT(skb), &vinfo);
260 Vnet_decref(vinfo);
261 if(err){
262 wprintf("> Failed security check vnet=%s src=%u.%u.%u.%u\n",
263 VnetId_ntoa(&vnet, vnetbuf),
264 NIPQUAD(saddr));
265 goto exit;
266 }
267 mine = 1;
268 // Point at the headers in the contained ethernet frame.
269 skb->mac.raw = skb_pull(skb, etherip_n);
271 // Know source ip, vnet, vmac, so could update varp cache.
272 // But if traffic comes to us over a vnetd tunnel this points the coa
273 // at the vnetd rather than the endpoint. So don't do it.
274 //varp_update(vnet, eth_hdr(skb)->h_source, skb->nh.iph->saddr);
276 // Assuming a standard Ethernet frame.
277 // Should check for protocol? Support ETH_P_8021Q too.
278 skb->nh.raw = skb_pull(skb, ETH_HLEN);
280 dprintf("> Unpacked vnet=%s srcmac=" MACFMT " dstmac=" MACFMT "\n",
281 VnetId_ntoa(&vnet, vnetbuf),
282 MAC6TUPLE(eth_hdr(skb)->h_source),
283 MAC6TUPLE(eth_hdr(skb)->h_dest));
285 #ifdef CONFIG_NETFILTER
286 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
287 // This stops our new pkt header being clobbered by a subsequent
288 // call to nf_bridge_maybe_copy_header.
289 // Code from nf_bridge_save_header() modidifed to use h_proto
290 // instead of skb->protocol.
291 if(skb->nf_bridge){
292 // Hmm. Standard ethernet header is ETH_HLEN (14),
293 // VLAN header (802.1q) is VLAN_ETH_HLEN (18).
294 // Where does 16 come from?
295 int header_size = 16;
296 if(eth_hdr(skb)->h_proto == __constant_htons(ETH_P_8021Q)) {
297 header_size = 18;
298 }
299 memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
300 }
301 #endif
302 #endif
304 if(1){
305 struct ethhdr *eth = eth_hdr(skb);
306 // Devices use eth_type_trans() to set skb->pkt_type and skb->protocol.
307 // Set them from contained ethhdr, or leave as received?
308 // 'Ware use of hard_header_len in eth_type_trans().
310 //skb->protocol = htons(ETH_P_IP);
312 if(ntohs(eth->h_proto) >= 1536){
313 skb->protocol = eth->h_proto;
314 } else {
315 skb->protocol = htons(ETH_P_802_2);
316 }
318 if(mac_is_multicast(eth->h_dest)){
319 if(mac_is_broadcast(eth->h_dest)){
320 skb->pkt_type = PACKET_BROADCAST;
321 } else {
322 skb->pkt_type = PACKET_MULTICAST;
323 }
324 } else {
325 skb->pkt_type = PACKET_HOST;
326 }
328 memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
329 if (skb->ip_summed == CHECKSUM_HW){
330 skb->ip_summed = CHECKSUM_NONE;
331 //skb->csum = csum_sub(skb->csum,
332 // csum_partial(skb->mac.raw, skb->nh.raw - skb->mac.raw, 0));
333 }
334 dst_release(skb->dst);
335 skb->dst = NULL;
337 #ifdef CONFIG_NETFILTER
338 nf_conntrack_put(skb->nfct);
339 skb->nfct = NULL;
340 #ifdef CONFIG_NETFILTER_DEBUG
341 skb->nf_debug = 0;
342 #endif
343 #endif
344 }
346 //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len + ETH_HLEN);
348 err = vnet_skb_recv(skb, &vnet, (Vmac*)eth_hdr(skb)->h_dest);
349 exit:
350 if(mine) err = 1;
351 dprintf("< skb=%p err=%d\n", skb, err);
352 return err;
353 }
355 /** Handle an ICMP error related to etherip.
356 *
357 * @param skb ICMP error packet
358 * @param info
359 */
360 static void etherip_protocol_icmp_err(struct sk_buff *skb, u32 info){
361 struct iphdr *iph = (struct iphdr*)skb->data;
363 wprintf("> ICMP error type=%d code=%d addr=" IPFMT "\n",
364 skb->h.icmph->type, skb->h.icmph->code, NIPQUAD(iph->daddr));
366 if (skb->h.icmph->type != ICMP_DEST_UNREACH ||
367 skb->h.icmph->code != ICMP_FRAG_NEEDED){
368 return;
369 }
370 wprintf("> MTU too big addr= " IPFMT "\n", NIPQUAD(iph->daddr));
371 }
373 //============================================================================
374 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
375 // Code for 2.6 kernel.
377 /** Etherip protocol. */
378 static struct net_protocol etherip_protocol = {
379 .handler = etherip_protocol_recv,
380 .err_handler = etherip_protocol_icmp_err,
381 };
383 static int etherip_protocol_add(void){
384 return inet_add_protocol(&etherip_protocol, IPPROTO_ETHERIP);
385 }
387 static int etherip_protocol_del(void){
388 return inet_del_protocol(&etherip_protocol, IPPROTO_ETHERIP);
389 }
391 //============================================================================
392 #else
393 //============================================================================
394 // Code for 2.4 kernel.
396 /** Etherip protocol. */
397 static struct inet_protocol etherip_protocol = {
398 .name = "ETHERIP",
399 .protocol = IPPROTO_ETHERIP,
400 .handler = etherip_protocol_recv,
401 .err_handler = etherip_protocol_icmp_err,
402 };
404 static int etherip_protocol_add(void){
405 inet_add_protocol(&etherip_protocol);
406 return 0;
407 }
409 static int etherip_protocol_del(void){
410 return inet_del_protocol(&etherip_protocol);
411 }
413 #endif
414 //============================================================================
417 /** Initialize the etherip module.
418 * Registers the etherip protocol.
419 *
420 * @return 0 on success, error code otherwise
421 */
422 int __init etherip_module_init(void) {
423 int err = 0;
424 etherip_protocol_add();
425 return err;
426 }
428 /** Finalize the etherip module.
429 * Deregisters the etherip protocol.
430 */
431 void __exit etherip_module_exit(void) {
432 if(etherip_protocol_del() < 0){
433 printk(KERN_INFO "%s: can't remove etherip protocol\n", __FUNCTION__);
434 }
435 }