1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved */
3 
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/inetdevice.h>
7 #include <net/switchdev.h>
8 
9 #include "prestera.h"
10 #include "prestera_router_hw.h"
11 
12 /* This util to be used, to convert kernel rules for default vr in hw_vr */
13 static u32 prestera_fix_tb_id(u32 tb_id)
14 {
15 	if (tb_id == RT_TABLE_UNSPEC ||
16 	    tb_id == RT_TABLE_LOCAL ||
17 	    tb_id == RT_TABLE_DEFAULT)
18 		tb_id = RT_TABLE_MAIN;
19 
20 	return tb_id;
21 }
22 
23 static int __prestera_inetaddr_port_event(struct net_device *port_dev,
24 					  unsigned long event,
25 					  struct netlink_ext_ack *extack)
26 {
27 	struct prestera_port *port = netdev_priv(port_dev);
28 	struct prestera_rif_entry_key re_key = {};
29 	struct prestera_rif_entry *re;
30 	u32 kern_tb_id;
31 	int err;
32 
33 	err = prestera_is_valid_mac_addr(port, port_dev->dev_addr);
34 	if (err) {
35 		NL_SET_ERR_MSG_MOD(extack, "RIF MAC must have the same prefix");
36 		return err;
37 	}
38 
39 	kern_tb_id = l3mdev_fib_table(port_dev);
40 	re_key.iface.type = PRESTERA_IF_PORT_E;
41 	re_key.iface.dev_port.hw_dev_num  = port->dev_id;
42 	re_key.iface.dev_port.port_num  = port->hw_id;
43 	re = prestera_rif_entry_find(port->sw, &re_key);
44 
45 	switch (event) {
46 	case NETDEV_UP:
47 		if (re) {
48 			NL_SET_ERR_MSG_MOD(extack, "RIF already exist");
49 			return -EEXIST;
50 		}
51 		re = prestera_rif_entry_create(port->sw, &re_key,
52 					       prestera_fix_tb_id(kern_tb_id),
53 					       port_dev->dev_addr);
54 		if (!re) {
55 			NL_SET_ERR_MSG_MOD(extack, "Can't create RIF");
56 			return -EINVAL;
57 		}
58 		dev_hold(port_dev);
59 		break;
60 	case NETDEV_DOWN:
61 		if (!re) {
62 			NL_SET_ERR_MSG_MOD(extack, "Can't find RIF");
63 			return -EEXIST;
64 		}
65 		prestera_rif_entry_destroy(port->sw, re);
66 		dev_put(port_dev);
67 		break;
68 	}
69 
70 	return 0;
71 }
72 
73 static int __prestera_inetaddr_event(struct prestera_switch *sw,
74 				     struct net_device *dev,
75 				     unsigned long event,
76 				     struct netlink_ext_ack *extack)
77 {
78 	if (!prestera_netdev_check(dev) || netif_is_bridge_port(dev) ||
79 	    netif_is_lag_port(dev) || netif_is_ovs_port(dev))
80 		return 0;
81 
82 	return __prestera_inetaddr_port_event(dev, event, extack);
83 }
84 
85 static int __prestera_inetaddr_cb(struct notifier_block *nb,
86 				  unsigned long event, void *ptr)
87 {
88 	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
89 	struct net_device *dev = ifa->ifa_dev->dev;
90 	struct prestera_router *router = container_of(nb,
91 						      struct prestera_router,
92 						      inetaddr_nb);
93 	struct in_device *idev;
94 	int err = 0;
95 
96 	if (event != NETDEV_DOWN)
97 		goto out;
98 
99 	/* Ignore if this is not latest address */
100 	idev = __in_dev_get_rtnl(dev);
101 	if (idev && idev->ifa_list)
102 		goto out;
103 
104 	err = __prestera_inetaddr_event(router->sw, dev, event, NULL);
105 out:
106 	return notifier_from_errno(err);
107 }
108 
109 static int __prestera_inetaddr_valid_cb(struct notifier_block *nb,
110 					unsigned long event, void *ptr)
111 {
112 	struct in_validator_info *ivi = (struct in_validator_info *)ptr;
113 	struct net_device *dev = ivi->ivi_dev->dev;
114 	struct prestera_router *router = container_of(nb,
115 						      struct prestera_router,
116 						      inetaddr_valid_nb);
117 	struct in_device *idev;
118 	int err = 0;
119 
120 	if (event != NETDEV_UP)
121 		goto out;
122 
123 	/* Ignore if this is not first address */
124 	idev = __in_dev_get_rtnl(dev);
125 	if (idev && idev->ifa_list)
126 		goto out;
127 
128 	if (ipv4_is_multicast(ivi->ivi_addr)) {
129 		NL_SET_ERR_MSG_MOD(ivi->extack,
130 				   "Multicast addr on RIF is not supported");
131 		err = -EINVAL;
132 		goto out;
133 	}
134 
135 	err = __prestera_inetaddr_event(router->sw, dev, event, ivi->extack);
136 out:
137 	return notifier_from_errno(err);
138 }
139 
140 int prestera_router_init(struct prestera_switch *sw)
141 {
142 	struct prestera_router *router;
143 	int err;
144 
145 	router = kzalloc(sizeof(*sw->router), GFP_KERNEL);
146 	if (!router)
147 		return -ENOMEM;
148 
149 	sw->router = router;
150 	router->sw = sw;
151 
152 	err = prestera_router_hw_init(sw);
153 	if (err)
154 		goto err_router_lib_init;
155 
156 	router->inetaddr_valid_nb.notifier_call = __prestera_inetaddr_valid_cb;
157 	err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
158 	if (err)
159 		goto err_register_inetaddr_validator_notifier;
160 
161 	router->inetaddr_nb.notifier_call = __prestera_inetaddr_cb;
162 	err = register_inetaddr_notifier(&router->inetaddr_nb);
163 	if (err)
164 		goto err_register_inetaddr_notifier;
165 
166 	return 0;
167 
168 err_register_inetaddr_notifier:
169 	unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
170 err_register_inetaddr_validator_notifier:
171 	prestera_router_hw_fini(sw);
172 err_router_lib_init:
173 	kfree(sw->router);
174 	return err;
175 }
176 
177 void prestera_router_fini(struct prestera_switch *sw)
178 {
179 	unregister_inetaddr_notifier(&sw->router->inetaddr_nb);
180 	unregister_inetaddr_validator_notifier(&sw->router->inetaddr_valid_nb);
181 	prestera_router_hw_fini(sw);
182 	kfree(sw->router);
183 	sw->router = NULL;
184 }
185