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>
42 static char *net1 = "eth1";
43 module_param(net1, charp, 0);
44 MODULE_PARM_DESC(net1, "The first net device name (default is eth1)");
46 static char *net2 = "eth2";
47 module_param(net2, charp, 0);
48 MODULE_PARM_DESC(net2, "The second net device name (default is eth2)");
50 static bool print = false;
51 module_param(print, bool, 0);
52 MODULE_PARM_DESC(print, "Log forwarding statistics (default is false)");
54 static int stats_interval = 10000;
55 module_param(stats_interval, int, 0);
56 MODULE_PARM_DESC(print, "Forwarding statistics packet interval (default is 10000)");
58 static bool terminate = false;
59 module_param(terminate, bool, 0);
60 MODULE_PARM_DESC(terminate, "Free skb instead of forwarding");
62 static struct net_device *dev1, *dev2;
65 static rx_handler_result_t netdev_frame_hook(struct sk_buff **pskb)
67 struct sk_buff *skb = *pskb;
68 struct net_device *dev;
70 if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
71 return RX_HANDLER_PASS;
73 dev = (struct net_device*) rcu_dereference_rtnl(skb->dev->rx_handler_data);
75 if ( ((count % stats_interval) == 0) && print )
76 printk("l2fwd count %d\n", count);
85 skb_push(skb, ETH_HLEN);
89 return RX_HANDLER_CONSUMED;
92 static int __init l2fwd_init_module(void)
96 dev1 = dev_get_by_name(&init_net, net1);
99 printk("can't get device %s\n", net1);
104 dev2 = dev_get_by_name(&init_net, net2);
107 printk("can't get device %s\n", net2);
113 err = netdev_rx_handler_register(dev1, netdev_frame_hook, dev2);
116 printk("can't register rx_handler for device %s\n", net1);
119 dev_set_promiscuity(dev1, 1);
121 err = netdev_rx_handler_register(dev2, netdev_frame_hook, dev1);
124 printk("can't register rx_handler for device %s\n", net2);
125 netdev_rx_handler_unregister(dev1);
128 dev_set_promiscuity(dev2, 1);
144 static void __exit l2fwd_exit_module(void)
150 netdev_rx_handler_unregister(dev1);
155 netdev_rx_handler_unregister(dev2);
157 dev_set_promiscuity(dev1, -1);
158 dev_set_promiscuity(dev2, -1);
162 module_init(l2fwd_init_module);
163 module_exit(l2fwd_exit_module);
165 MODULE_DESCRIPTION("Huawei L2 Forwarding module");
166 MODULE_LICENSE("GPL");
167 MODULE_VERSION("0.1");