3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
11 static unsigned int ipvlan_netid __read_mostly;
14 unsigned int ipvl_nf_hook_refcnt;
17 static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
18 struct net_device *dev)
20 struct ipvl_addr *addr = NULL;
21 struct ipvl_port *port;
25 if (!dev || !netif_is_ipvlan_port(dev))
28 port = ipvlan_port_get_rcu(dev);
29 if (!port || port->mode != IPVLAN_MODE_L3S)
32 lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
36 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
41 static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev,
42 struct sk_buff *skb, u16 proto)
44 struct ipvl_addr *addr;
45 struct net_device *sdev;
47 addr = ipvlan_skb_to_addr(skb, dev);
51 sdev = addr->master->dev;
55 struct iphdr *ip4h = ip_hdr(skb);
58 err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
64 #if IS_ENABLED(CONFIG_IPV6)
67 struct dst_entry *dst;
68 struct ipv6hdr *ip6h = ipv6_hdr(skb);
69 int flags = RT6_LOOKUP_F_HAS_SADDR;
71 .flowi6_iif = sdev->ifindex,
74 .flowlabel = ip6_flowinfo(ip6h),
75 .flowi6_mark = skb->mark,
76 .flowi6_proto = ip6h->nexthdr,
80 dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6,
82 skb_dst_set(skb, dst);
93 static const struct l3mdev_ops ipvl_l3mdev_ops = {
94 .l3mdev_l3_rcv = ipvlan_l3_rcv,
97 static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
98 const struct nf_hook_state *state)
100 struct ipvl_addr *addr;
103 addr = ipvlan_skb_to_addr(skb, skb->dev);
107 skb->dev = addr->master->dev;
108 len = skb->len + ETH_HLEN;
109 ipvlan_count_rx(addr->master, len, true, false);
114 static const struct nf_hook_ops ipvl_nfops[] = {
116 .hook = ipvlan_nf_input,
118 .hooknum = NF_INET_LOCAL_IN,
121 #if IS_ENABLED(CONFIG_IPV6)
123 .hook = ipvlan_nf_input,
125 .hooknum = NF_INET_LOCAL_IN,
131 static int ipvlan_register_nf_hook(struct net *net)
133 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
136 if (!vnet->ipvl_nf_hook_refcnt) {
137 err = nf_register_net_hooks(net, ipvl_nfops,
138 ARRAY_SIZE(ipvl_nfops));
140 vnet->ipvl_nf_hook_refcnt = 1;
142 vnet->ipvl_nf_hook_refcnt++;
148 static void ipvlan_unregister_nf_hook(struct net *net)
150 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
152 if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
155 vnet->ipvl_nf_hook_refcnt--;
156 if (!vnet->ipvl_nf_hook_refcnt)
157 nf_unregister_net_hooks(net, ipvl_nfops,
158 ARRAY_SIZE(ipvl_nfops));
161 void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet)
163 struct ipvlan_netns *old_vnet;
167 old_vnet = net_generic(oldnet, ipvlan_netid);
168 if (!old_vnet->ipvl_nf_hook_refcnt)
171 ipvlan_register_nf_hook(newnet);
172 ipvlan_unregister_nf_hook(oldnet);
175 static void ipvlan_ns_exit(struct net *net)
177 struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
179 if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
180 vnet->ipvl_nf_hook_refcnt = 0;
181 nf_unregister_net_hooks(net, ipvl_nfops,
182 ARRAY_SIZE(ipvl_nfops));
186 static struct pernet_operations ipvlan_net_ops = {
188 .size = sizeof(struct ipvlan_netns),
189 .exit = ipvlan_ns_exit,
192 int ipvlan_l3s_init(void)
194 return register_pernet_subsys(&ipvlan_net_ops);
197 void ipvlan_l3s_cleanup(void)
199 unregister_pernet_subsys(&ipvlan_net_ops);
202 int ipvlan_l3s_register(struct ipvl_port *port)
204 struct net_device *dev = port->dev;
209 ret = ipvlan_register_nf_hook(read_pnet(&port->pnet));
211 dev->l3mdev_ops = &ipvl_l3mdev_ops;
212 dev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
218 void ipvlan_l3s_unregister(struct ipvl_port *port)
220 struct net_device *dev = port->dev;
224 dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
225 ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
226 dev->l3mdev_ops = NULL;