1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
7 static unsigned int ipvlan_netid __read_mostly
;
10 unsigned int ipvl_nf_hook_refcnt
;
13 static struct ipvl_addr
*ipvlan_skb_to_addr(struct sk_buff
*skb
,
14 struct net_device
*dev
)
16 struct ipvl_addr
*addr
= NULL
;
17 struct ipvl_port
*port
;
21 if (!dev
|| !netif_is_ipvlan_port(dev
))
24 port
= ipvlan_port_get_rcu(dev
);
25 if (!port
|| port
->mode
!= IPVLAN_MODE_L3S
)
28 lyr3h
= ipvlan_get_L3_hdr(port
, skb
, &addr_type
);
32 addr
= ipvlan_addr_lookup(port
, lyr3h
, addr_type
, true);
37 static struct sk_buff
*ipvlan_l3_rcv(struct net_device
*dev
,
38 struct sk_buff
*skb
, u16 proto
)
40 struct ipvl_addr
*addr
;
41 struct net_device
*sdev
;
43 addr
= ipvlan_skb_to_addr(skb
, dev
);
47 sdev
= addr
->master
->dev
;
51 struct iphdr
*ip4h
= ip_hdr(skb
);
54 err
= ip_route_input_noref(skb
, ip4h
->daddr
, ip4h
->saddr
,
60 #if IS_ENABLED(CONFIG_IPV6)
63 struct dst_entry
*dst
;
64 struct ipv6hdr
*ip6h
= ipv6_hdr(skb
);
65 int flags
= RT6_LOOKUP_F_HAS_SADDR
;
67 .flowi6_iif
= sdev
->ifindex
,
70 .flowlabel
= ip6_flowinfo(ip6h
),
71 .flowi6_mark
= skb
->mark
,
72 .flowi6_proto
= ip6h
->nexthdr
,
76 dst
= ip6_route_input_lookup(dev_net(sdev
), sdev
, &fl6
,
78 skb_dst_set(skb
, dst
);
89 static const struct l3mdev_ops ipvl_l3mdev_ops
= {
90 .l3mdev_l3_rcv
= ipvlan_l3_rcv
,
93 static unsigned int ipvlan_nf_input(void *priv
, struct sk_buff
*skb
,
94 const struct nf_hook_state
*state
)
96 struct ipvl_addr
*addr
;
99 addr
= ipvlan_skb_to_addr(skb
, skb
->dev
);
103 skb
->dev
= addr
->master
->dev
;
104 len
= skb
->len
+ ETH_HLEN
;
105 ipvlan_count_rx(addr
->master
, len
, true, false);
110 static const struct nf_hook_ops ipvl_nfops
[] = {
112 .hook
= ipvlan_nf_input
,
114 .hooknum
= NF_INET_LOCAL_IN
,
117 #if IS_ENABLED(CONFIG_IPV6)
119 .hook
= ipvlan_nf_input
,
121 .hooknum
= NF_INET_LOCAL_IN
,
127 static int ipvlan_register_nf_hook(struct net
*net
)
129 struct ipvlan_netns
*vnet
= net_generic(net
, ipvlan_netid
);
132 if (!vnet
->ipvl_nf_hook_refcnt
) {
133 err
= nf_register_net_hooks(net
, ipvl_nfops
,
134 ARRAY_SIZE(ipvl_nfops
));
136 vnet
->ipvl_nf_hook_refcnt
= 1;
138 vnet
->ipvl_nf_hook_refcnt
++;
144 static void ipvlan_unregister_nf_hook(struct net
*net
)
146 struct ipvlan_netns
*vnet
= net_generic(net
, ipvlan_netid
);
148 if (WARN_ON(!vnet
->ipvl_nf_hook_refcnt
))
151 vnet
->ipvl_nf_hook_refcnt
--;
152 if (!vnet
->ipvl_nf_hook_refcnt
)
153 nf_unregister_net_hooks(net
, ipvl_nfops
,
154 ARRAY_SIZE(ipvl_nfops
));
157 void ipvlan_migrate_l3s_hook(struct net
*oldnet
, struct net
*newnet
)
159 struct ipvlan_netns
*old_vnet
;
163 old_vnet
= net_generic(oldnet
, ipvlan_netid
);
164 if (!old_vnet
->ipvl_nf_hook_refcnt
)
167 ipvlan_register_nf_hook(newnet
);
168 ipvlan_unregister_nf_hook(oldnet
);
171 static void ipvlan_ns_exit(struct net
*net
)
173 struct ipvlan_netns
*vnet
= net_generic(net
, ipvlan_netid
);
175 if (WARN_ON_ONCE(vnet
->ipvl_nf_hook_refcnt
)) {
176 vnet
->ipvl_nf_hook_refcnt
= 0;
177 nf_unregister_net_hooks(net
, ipvl_nfops
,
178 ARRAY_SIZE(ipvl_nfops
));
182 static struct pernet_operations ipvlan_net_ops
= {
184 .size
= sizeof(struct ipvlan_netns
),
185 .exit
= ipvlan_ns_exit
,
188 int ipvlan_l3s_init(void)
190 return register_pernet_subsys(&ipvlan_net_ops
);
193 void ipvlan_l3s_cleanup(void)
195 unregister_pernet_subsys(&ipvlan_net_ops
);
198 int ipvlan_l3s_register(struct ipvl_port
*port
)
200 struct net_device
*dev
= port
->dev
;
205 ret
= ipvlan_register_nf_hook(read_pnet(&port
->pnet
));
207 dev
->l3mdev_ops
= &ipvl_l3mdev_ops
;
208 dev
->priv_flags
|= IFF_L3MDEV_RX_HANDLER
;
214 void ipvlan_l3s_unregister(struct ipvl_port
*port
)
216 struct net_device
*dev
= port
->dev
;
220 dev
->priv_flags
&= ~IFF_L3MDEV_RX_HANDLER
;
221 ipvlan_unregister_nf_hook(read_pnet(&port
->pnet
));
222 dev
->l3mdev_ops
= NULL
;