2 * Copyright 2015 Futurewei Inc.
4 * l2fwd is free software: you can redistribute it and/or modify
5 * it under the terms of version 2 the GNU General Public License as published
6 * by the Free Software Foundation only
8 * l2fwd is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this code. If not, see
15 * https://www.gnu.org/licenses/gpl-2.0.html
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
29 #include <linux/init.h>
30 #include <linux/interrupt.h>
31 #include <linux/pci.h>
32 #include <linux/aer.h>
33 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
36 #include <linux/if_ether.h>
38 #include <linux/rtnetlink.h>
39 #include <linux/prefetch.h>
40 #include <linux/log2.h>
41 #include <linux/gfp.h>
42 #include <linux/slab.h>
46 #include <linux/icmp.h>
47 #include <linux/inetdevice.h>
50 static char *net1 = "eth1";
51 module_param(net1, charp, 0);
52 MODULE_PARM_DESC(net1, "The first net device name and optional DNAT parameters (default is eth1)");
54 static char *net2 = "eth2";
55 module_param(net2, charp, 0);
56 MODULE_PARM_DESC(net2, "The second net device name and optional DNAT parameters (default is eth2)");
58 static bool print = false;
59 module_param(print, bool, 0);
60 MODULE_PARM_DESC(print, "Log forwarding statistics (default is false)");
62 static int stats_interval = 10;
63 module_param(stats_interval, int, 0);
64 MODULE_PARM_DESC(print, "Forwarding statistics packet interval (default is 10000)");
66 static bool terminate = false;
67 module_param(terminate, bool, 0);
68 MODULE_PARM_DESC(terminate, "Free skb instead of forwarding");
70 static struct net_device *dev1, *dev2;
79 static uint octet0[4];
81 static u8 s_octet0[4];
84 static uint octet1[4];
86 static u8 s_octet1[4];
88 static rx_handler_result_t netdev_frame_hook(struct sk_buff **pskb)
90 struct sk_buff *skb = *pskb;
91 struct net_device *dev;
92 char *data = skb->data;
93 struct ethhdr *eh = (struct ethhdr *)skb_mac_header(skb);
94 struct iphdr *ih = (struct iphdr *)skb_network_header(skb);
95 struct icmphdr *icmph = icmp_hdr(skb);
97 rx_handler_result_t retval = RX_HANDLER_CONSUMED;
99 if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
100 return RX_HANDLER_PASS;
102 dev = (struct net_device*) rcu_dereference_rtnl(skb->dev->rx_handler_data);
104 if ( ((count % stats_interval) == 0) && print )
105 printk("l2fwd count %d\n", count);
114 u32 *daddr = &(ih->daddr);
115 u32 *saddr = &(ih->saddr);
116 unsigned short proto = ntohs(eh->h_proto);
118 uint use_dnat = dev == dev1 ? dnat_enabled.eth1:dnat_enabled.eth2;
120 if (unlikely(proto != ETH_P_IP ))
121 return RX_HANDLER_PASS;
124 printk("use_dnat %d proto %x ETH_P_IP %x Dest MAC - IP %d.%d.%d.%d MAC %x:%x:%x:%x:%x:%x\n",use_dnat,proto,ETH_P_IP,(u8)daddr[0],(u8)daddr[1],(u8)daddr[2],(u8)daddr[3],eh->h_dest[0],eh->h_dest[1],eh->h_dest[2],eh->h_dest[3],eh->h_dest[4],eh->h_dest[5]);
126 if ( (use_dnat == 1) && (proto == ETH_P_IP) )
128 unsigned int *t_addr = dev == dev1 ? &octet0[0]:&octet1[0];
129 u8 *s_addr = dev == dev1 ? &s_octet0[0]:&s_octet1[0];
132 ((u8 *)daddr)[0] = (u8)t_addr[0];
133 ((u8 *)daddr)[1] = (u8)t_addr[1];
134 ((u8 *)daddr)[2] = (u8)t_addr[2];
135 ((u8 *)daddr)[3] = (u8)t_addr[3];
137 t_addr = dev == dev1 ? &mac0[0]:&mac1[0];
139 eh->h_dest[0] = (unsigned char)t_addr[0];
140 eh->h_dest[1] = (unsigned char)t_addr[1];
141 eh->h_dest[2] = (unsigned char)t_addr[2];
142 eh->h_dest[3] = (unsigned char)t_addr[3];
143 eh->h_dest[4] = (unsigned char)t_addr[4];
144 eh->h_dest[5] = (unsigned char)t_addr[5];
147 printk("After DNAT: Dest MAC - IP %d.%d.%d.%d MAC %x:%x:%x:%x:%x:%x\n",daddr[0],daddr[1],daddr[2],daddr[3],eh->h_dest[0],eh->h_dest[1],eh->h_dest[2],eh->h_dest[3],eh->h_dest[4],eh->h_dest[5]);
150 eh->h_source[0] = (unsigned char)dev->dev_addr[0];
151 eh->h_source[1] = (unsigned char)dev->dev_addr[1];
152 eh->h_source[2] = (unsigned char)dev->dev_addr[2];
153 eh->h_source[3] = (unsigned char)dev->dev_addr[3];
154 eh->h_source[4] = (unsigned char)dev->dev_addr[4];
155 eh->h_source[5] = (unsigned char)dev->dev_addr[5];
157 ((u8 *)saddr)[0] = s_addr[0];
158 ((u8 *)saddr)[1] = s_addr[1];
159 ((u8 *)saddr)[2] = s_addr[2];
160 ((u8 *)saddr)[3] = s_addr[3];
162 skb->ip_summed = CHECKSUM_COMPLETE;
163 skb->csum = skb_checksum_complete(skb);
165 ih->check = ip_fast_csum((unsigned char *)ih, ih->ihl);
168 printk("After DNAT: Source MAC - IP %d.%d.%d.%d MAC %u:%u:%u:%u:%u:%u\n",saddr[0],saddr[1],saddr[2],saddr[3],eh->h_source[0],eh->h_source[1],eh->h_source[2],eh->h_source[3],eh->h_source[4],eh->h_source[5]);
173 skb_push(skb, ETH_HLEN);
180 static int __init l2fwd_init_module(void)
185 char *dnat_fmt_suffix = " %3d.%3d.%3d.%3d %2x:%2x:%2x:%2x:%2x:%2x";
187 char name_fmt_str[IFNAMSIZ+1];
188 char t_name[IFNAMSIZ+1];
192 sprintf(name_fmt_str,"%%%ds",IFNAMSIZ);
193 dnat_fmt = (char *)kmalloc(strlen(name_fmt_str)+strlen(dnat_fmt_suffix)+1,GFP_KERNEL);
194 sprintf(dnat_fmt,"%s%s",name_fmt_str,dnat_fmt_suffix);
197 while(*t_ptr != '\0') *t_ptr == ',' ? *t_ptr++ = ' ':*t_ptr++;
199 fCount = sscanf(net1,dnat_fmt,t_name,&octet0[0],&octet0[1],&octet0[2],
200 &octet0[3],&mac0[0],&mac0[1],
201 &mac0[2],&mac0[3],&mac0[4],&mac0[5]);
203 dev1 = dev_get_by_name(&init_net, t_name);
206 printk("can't get device %s\n", t_name);
210 if (fCount >1 && fCount <11 )
212 printk("Both DNAT IP and Mac Address must be provided\n");
216 else if (fCount==11 )
218 struct in_device *in_dev = rcu_dereference(dev1->ip_ptr);
220 struct in_ifaddr *ifap;
222 dnat_enabled.eth1 = 1;
223 // in_dev has a list of IP addresses (because an interface can have multiple)
224 for (ifap = in_dev->ifa_list; ifap != NULL;
225 ifap = ifap->ifa_next)
227 ifaddr = ifap->ifa_address; // is the IPv4 address
231 printk("%s interface ip address list is null!\n",t_name);
236 s_octet0[0] = ((u8 *)&ifaddr)[0];
237 s_octet0[1] = ((u8 *)&ifaddr)[1];
238 s_octet0[2] = ((u8 *)&ifaddr)[2];
239 s_octet0[3] = ((u8 *)&ifaddr)[3];
241 s_mac0[0] = dev1->dev_addr[0];
242 s_mac0[1] = dev1->dev_addr[1];
243 s_mac0[2] = dev1->dev_addr[2];
244 s_mac0[3] = dev1->dev_addr[3];
245 s_mac0[4] = dev1->dev_addr[4];
246 s_mac0[5] = dev1->dev_addr[5];
249 printk("DNAT Enabled for %s IP %d.%d.%d.%d MAC %x:%x:%x:%x:%x:%x\n",t_name,octet0[0],octet0[1],octet0[2],octet0[3],mac0[0],mac0[1],mac0[2],mac0[3],mac0[4],mac0[5]);
250 printk("SNAT IP %d.%d.%d.%d SNAT MAC %x:%x:%x:%x:%x:%x\n",s_octet0[0],s_octet0[1],s_octet0[2],s_octet0[3],s_mac0[0],s_mac0[1],s_mac0[2],s_mac0[3],s_mac0[4],mac0[5]);
254 printk("Pure Level 2 forward enabled for %s\n",t_name);
260 while(*t_ptr != '\0') *t_ptr == ',' ? *t_ptr++ = ' ':*t_ptr++;
262 fCount = sscanf(net2,dnat_fmt,t_name,&octet1[0],&octet1[1],&octet1[2],&octet1[3],&mac1[0],&mac1[1],&mac1[2],&mac1[3],&mac1[4],&mac1[5]);
264 dev2 = dev_get_by_name(&init_net, t_name);
267 printk("can't get device %s\n", t_name);
271 if (fCount >1 && fCount <11 )
273 printk("Both DNAT IP and Mac Address must be provided\n");
277 else if (fCount==11 )
279 struct in_device *in_dev = rcu_dereference(dev2->ip_ptr);
281 struct in_ifaddr *ifap;
282 // dev has a list of IP addresses (because an interface can have multiple)
283 dnat_enabled.eth2 = 1;
284 for (ifap = in_dev->ifa_list; ifap != NULL;
285 ifap = ifap->ifa_next)
287 ifaddr = ifap->ifa_address; // is the IPv4 address
291 printk("%s interface ip address list is null!\n",t_name);
295 /* ifa_local: ifa_address is the remote point in ppp */
297 s_octet1[0] = ((u8 *)&ifaddr)[0];
298 s_octet1[1] = ((u8 *)&ifaddr)[1];
299 s_octet1[2] = ((u8 *)&ifaddr)[2];
300 s_octet1[3] = ((u8 *)&ifaddr)[3];
302 s_mac1[0] = dev2->dev_addr[0];
303 s_mac1[1] = dev2->dev_addr[1];
304 s_mac1[2] = dev2->dev_addr[2];
305 s_mac1[3] = dev2->dev_addr[3];
306 s_mac1[4] = dev2->dev_addr[4];
307 s_mac1[5] = dev2->dev_addr[5];
310 printk("DNAT Enabled for %s IP %d.%d.%d.%d MAC %x:%x:%x:%x:%x:%x\n",t_name,octet1[0],octet1[1],octet1[2],octet1[3],mac1[0],mac1[1],mac1[2],mac1[3],mac1[4],mac1[5]);
311 printk("SNAT IP %d.%d.%d.%d SNAT MAC %x:%x:%x:%x:%x:%x\n",s_octet1[0],s_octet1[1],s_octet1[2],s_octet1[3],s_mac1[0],s_mac1[1],s_mac1[2],s_mac1[3],s_mac1[4],mac1[5]);
315 printk("Level 2 forward enabled for %s\n",t_name);
320 err = netdev_rx_handler_register(dev1, netdev_frame_hook, dev2);
323 printk("can't register rx_handler for device %s\n", net1);
326 dev_set_promiscuity(dev1, 1);
328 err = netdev_rx_handler_register(dev2, netdev_frame_hook, dev1);
331 printk("can't register rx_handler for device %s\n", net2);
332 netdev_rx_handler_unregister(dev1);
336 dev_set_promiscuity(dev2, 1);
352 static void __exit l2fwd_exit_module(void)
358 netdev_rx_handler_unregister(dev1);
363 netdev_rx_handler_unregister(dev2);
365 dev_set_promiscuity(dev1, -1);
366 dev_set_promiscuity(dev2, -1);
370 module_init(l2fwd_init_module);
371 module_exit(l2fwd_exit_module);
373 MODULE_DESCRIPTION("Huawei L2 Forwarding module with DNAT");
374 MODULE_LICENSE("GPL");
375 MODULE_VERSION("1.0");