hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/net/ipvlan/ipvlan_main.c
....@@ -1,80 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
2
- *
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.
7
- *
83 */
94
105 #include "ipvlan.h"
116
12
-static unsigned int ipvlan_netid __read_mostly;
13
-
14
-struct ipvlan_netns {
15
- unsigned int ipvl_nf_hook_refcnt;
16
-};
17
-
18
-static const struct nf_hook_ops ipvl_nfops[] = {
19
- {
20
- .hook = ipvlan_nf_input,
21
- .pf = NFPROTO_IPV4,
22
- .hooknum = NF_INET_LOCAL_IN,
23
- .priority = INT_MAX,
24
- },
25
-#if IS_ENABLED(CONFIG_IPV6)
26
- {
27
- .hook = ipvlan_nf_input,
28
- .pf = NFPROTO_IPV6,
29
- .hooknum = NF_INET_LOCAL_IN,
30
- .priority = INT_MAX,
31
- },
32
-#endif
33
-};
34
-
35
-static const struct l3mdev_ops ipvl_l3mdev_ops = {
36
- .l3mdev_l3_rcv = ipvlan_l3_rcv,
37
-};
38
-
39
-static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
40
-{
41
- ipvlan->dev->mtu = dev->mtu;
42
-}
43
-
44
-static int ipvlan_register_nf_hook(struct net *net)
45
-{
46
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
47
- int err = 0;
48
-
49
- if (!vnet->ipvl_nf_hook_refcnt) {
50
- err = nf_register_net_hooks(net, ipvl_nfops,
51
- ARRAY_SIZE(ipvl_nfops));
52
- if (!err)
53
- vnet->ipvl_nf_hook_refcnt = 1;
54
- } else {
55
- vnet->ipvl_nf_hook_refcnt++;
56
- }
57
-
58
- return err;
59
-}
60
-
61
-static void ipvlan_unregister_nf_hook(struct net *net)
62
-{
63
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
64
-
65
- if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
66
- return;
67
-
68
- vnet->ipvl_nf_hook_refcnt--;
69
- if (!vnet->ipvl_nf_hook_refcnt)
70
- nf_unregister_net_hooks(net, ipvl_nfops,
71
- ARRAY_SIZE(ipvl_nfops));
72
-}
73
-
74
-static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval)
7
+static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
8
+ struct netlink_ext_ack *extack)
759 {
7610 struct ipvl_dev *ipvlan;
77
- struct net_device *mdev = port->dev;
7811 unsigned int flags;
7912 int err;
8013
....@@ -84,27 +17,24 @@
8417 flags = ipvlan->dev->flags;
8518 if (nval == IPVLAN_MODE_L3 || nval == IPVLAN_MODE_L3S) {
8619 err = dev_change_flags(ipvlan->dev,
87
- flags | IFF_NOARP);
20
+ flags | IFF_NOARP,
21
+ extack);
8822 } else {
8923 err = dev_change_flags(ipvlan->dev,
90
- flags & ~IFF_NOARP);
24
+ flags & ~IFF_NOARP,
25
+ extack);
9126 }
9227 if (unlikely(err))
9328 goto fail;
9429 }
9530 if (nval == IPVLAN_MODE_L3S) {
9631 /* New mode is L3S */
97
- err = ipvlan_register_nf_hook(read_pnet(&port->pnet));
98
- if (!err) {
99
- mdev->l3mdev_ops = &ipvl_l3mdev_ops;
100
- mdev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
101
- } else
32
+ err = ipvlan_l3s_register(port);
33
+ if (err)
10234 goto fail;
10335 } else if (port->mode == IPVLAN_MODE_L3S) {
10436 /* Old mode was L3S */
105
- mdev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
106
- ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
107
- mdev->l3mdev_ops = NULL;
37
+ ipvlan_l3s_unregister(port);
10838 }
10939 port->mode = nval;
11040 }
....@@ -116,9 +46,11 @@
11646 flags = ipvlan->dev->flags;
11747 if (port->mode == IPVLAN_MODE_L3 ||
11848 port->mode == IPVLAN_MODE_L3S)
119
- dev_change_flags(ipvlan->dev, flags | IFF_NOARP);
49
+ dev_change_flags(ipvlan->dev, flags | IFF_NOARP,
50
+ NULL);
12051 else
121
- dev_change_flags(ipvlan->dev, flags & ~IFF_NOARP);
52
+ dev_change_flags(ipvlan->dev, flags & ~IFF_NOARP,
53
+ NULL);
12254 }
12355
12456 return err;
....@@ -161,11 +93,8 @@
16193 struct ipvl_port *port = ipvlan_port_get_rtnl(dev);
16294 struct sk_buff *skb;
16395
164
- if (port->mode == IPVLAN_MODE_L3S) {
165
- dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
166
- ipvlan_unregister_nf_hook(dev_net(dev));
167
- dev->l3mdev_ops = NULL;
168
- }
96
+ if (port->mode == IPVLAN_MODE_L3S)
97
+ ipvlan_l3s_unregister(port);
16998 netdev_rx_handler_unregister(dev);
17099 cancel_work_sync(&port->wq);
171100 while ((skb = __skb_dequeue(&port->backlog)) != NULL) {
....@@ -186,8 +115,8 @@
186115
187116 #define IPVLAN_FEATURES \
188117 (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
189
- NETIF_F_GSO | NETIF_F_TSO | NETIF_F_GSO_ROBUST | \
190
- NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
118
+ NETIF_F_GSO | NETIF_F_ALL_TSO | NETIF_F_GSO_ROBUST | \
119
+ NETIF_F_GRO | NETIF_F_RXCSUM | \
191120 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
192121
193122 /* NETIF_F_GSO_ENCAP_ALL NETIF_F_GSO_SOFTWARE Newly added */
....@@ -208,6 +137,7 @@
208137 dev->features |= IPVLAN_ALWAYS_ON;
209138 dev->vlan_features = phy_dev->vlan_features & IPVLAN_FEATURES;
210139 dev->vlan_features |= IPVLAN_ALWAYS_ON_OFLOADS;
140
+ dev->hw_enc_features |= dev->features;
211141 dev->gso_max_size = phy_dev->gso_max_size;
212142 dev->gso_max_segs = phy_dev->gso_max_segs;
213143 dev->hard_header_len = phy_dev->hard_header_len;
....@@ -456,6 +386,11 @@
456386 .cache_update = eth_header_cache_update,
457387 };
458388
389
+static void ipvlan_adjust_mtu(struct ipvl_dev *ipvlan, struct net_device *dev)
390
+{
391
+ ipvlan->dev->mtu = dev->mtu;
392
+}
393
+
459394 static bool netif_is_ipvlan(const struct net_device *dev)
460395 {
461396 /* both ipvlan and ipvtap devices use the same netdev_ops */
....@@ -515,7 +450,7 @@
515450 if (data[IFLA_IPVLAN_MODE]) {
516451 u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
517452
518
- err = ipvlan_set_port_mode(port, nmode);
453
+ err = ipvlan_set_port_mode(port, nmode, extack);
519454 }
520455
521456 if (!err && data[IFLA_IPVLAN_FLAGS]) {
....@@ -552,7 +487,7 @@
552487 if (data[IFLA_IPVLAN_MODE]) {
553488 u16 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
554489
555
- if (mode < IPVLAN_MODE_L2 || mode >= IPVLAN_MODE_MAX)
490
+ if (mode >= IPVLAN_MODE_MAX)
556491 return -EINVAL;
557492 }
558493 if (data[IFLA_IPVLAN_FLAGS]) {
....@@ -691,7 +626,7 @@
691626 if (data && data[IFLA_IPVLAN_MODE])
692627 mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
693628
694
- err = ipvlan_set_port_mode(port, mode);
629
+ err = ipvlan_set_port_mode(port, mode, extack);
695630 if (err)
696631 goto unlink_netdev;
697632
....@@ -749,6 +684,13 @@
749684 [IFLA_IPVLAN_FLAGS] = { .type = NLA_U16 },
750685 };
751686
687
+static struct net *ipvlan_get_link_net(const struct net_device *dev)
688
+{
689
+ struct ipvl_dev *ipvlan = netdev_priv(dev);
690
+
691
+ return dev_net(ipvlan->phy_dev);
692
+}
693
+
752694 static struct rtnl_link_ops ipvlan_link_ops = {
753695 .kind = "ipvlan",
754696 .priv_size = sizeof(struct ipvl_dev),
....@@ -756,6 +698,7 @@
756698 .setup = ipvlan_link_setup,
757699 .newlink = ipvlan_link_new,
758700 .dellink = ipvlan_link_delete,
701
+ .get_link_net = ipvlan_get_link_net,
759702 };
760703
761704 int ipvlan_link_register(struct rtnl_link_ops *ops)
....@@ -773,10 +716,13 @@
773716 static int ipvlan_device_event(struct notifier_block *unused,
774717 unsigned long event, void *ptr)
775718 {
719
+ struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr);
720
+ struct netdev_notifier_pre_changeaddr_info *prechaddr_info;
776721 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
777722 struct ipvl_dev *ipvlan, *next;
778723 struct ipvl_port *port;
779724 LIST_HEAD(lst_kill);
725
+ int err;
780726
781727 if (!netif_is_ipvlan_port(dev))
782728 return NOTIFY_DONE;
....@@ -792,7 +738,6 @@
792738
793739 case NETDEV_REGISTER: {
794740 struct net *oldnet, *newnet = dev_net(dev);
795
- struct ipvlan_netns *old_vnet;
796741
797742 oldnet = read_pnet(&port->pnet);
798743 if (net_eq(newnet, oldnet))
....@@ -800,12 +745,7 @@
800745
801746 write_pnet(&port->pnet, newnet);
802747
803
- old_vnet = net_generic(oldnet, ipvlan_netid);
804
- if (!old_vnet->ipvl_nf_hook_refcnt)
805
- break;
806
-
807
- ipvlan_register_nf_hook(newnet);
808
- ipvlan_unregister_nf_hook(oldnet);
748
+ ipvlan_migrate_l3s_hook(oldnet, newnet);
809749 break;
810750 }
811751 case NETDEV_UNREGISTER:
....@@ -829,6 +769,17 @@
829769 case NETDEV_CHANGEMTU:
830770 list_for_each_entry(ipvlan, &port->ipvlans, pnode)
831771 ipvlan_adjust_mtu(ipvlan, dev);
772
+ break;
773
+
774
+ case NETDEV_PRE_CHANGEADDR:
775
+ prechaddr_info = ptr;
776
+ list_for_each_entry(ipvlan, &port->ipvlans, pnode) {
777
+ err = dev_pre_changeaddr_notify(ipvlan->dev,
778
+ prechaddr_info->dev_addr,
779
+ extack);
780
+ if (err)
781
+ return notifier_from_errno(err);
782
+ }
832783 break;
833784
834785 case NETDEV_CHANGEADDR:
....@@ -1067,23 +1018,6 @@
10671018 };
10681019 #endif
10691020
1070
-static void ipvlan_ns_exit(struct net *net)
1071
-{
1072
- struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
1073
-
1074
- if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
1075
- vnet->ipvl_nf_hook_refcnt = 0;
1076
- nf_unregister_net_hooks(net, ipvl_nfops,
1077
- ARRAY_SIZE(ipvl_nfops));
1078
- }
1079
-}
1080
-
1081
-static struct pernet_operations ipvlan_net_ops = {
1082
- .id = &ipvlan_netid,
1083
- .size = sizeof(struct ipvlan_netns),
1084
- .exit = ipvlan_ns_exit,
1085
-};
1086
-
10871021 static int __init ipvlan_init_module(void)
10881022 {
10891023 int err;
....@@ -1098,13 +1032,13 @@
10981032 register_inetaddr_notifier(&ipvlan_addr4_notifier_block);
10991033 register_inetaddr_validator_notifier(&ipvlan_addr4_vtor_notifier_block);
11001034
1101
- err = register_pernet_subsys(&ipvlan_net_ops);
1035
+ err = ipvlan_l3s_init();
11021036 if (err < 0)
11031037 goto error;
11041038
11051039 err = ipvlan_link_register(&ipvlan_link_ops);
11061040 if (err < 0) {
1107
- unregister_pernet_subsys(&ipvlan_net_ops);
1041
+ ipvlan_l3s_cleanup();
11081042 goto error;
11091043 }
11101044
....@@ -1125,7 +1059,7 @@
11251059 static void __exit ipvlan_cleanup_module(void)
11261060 {
11271061 rtnl_link_unregister(&ipvlan_link_ops);
1128
- unregister_pernet_subsys(&ipvlan_net_ops);
1062
+ ipvlan_l3s_cleanup();
11291063 unregister_netdevice_notifier(&ipvlan_notifier_block);
11301064 unregister_inetaddr_notifier(&ipvlan_addr4_notifier_block);
11311065 unregister_inetaddr_validator_notifier(