xref: /openbmc/linux/net/caif/chnl_net.c (revision 79c98128)
1 /*
2  * Copyright (C) ST-Ericsson AB 2010
3  * Authors:	Sjur Brendeland/sjur.brandeland@stericsson.com
4  *		Daniel Martensson / Daniel.Martensson@stericsson.com
5  * License terms: GNU General Public License (GPL) version 2
6  */
7 
8 #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
9 
10 #include <linux/version.h>
11 #include <linux/fs.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/netdevice.h>
15 #include <linux/if_ether.h>
16 #include <linux/moduleparam.h>
17 #include <linux/ip.h>
18 #include <linux/sched.h>
19 #include <linux/sockios.h>
20 #include <linux/caif/if_caif.h>
21 #include <net/rtnetlink.h>
22 #include <net/caif/caif_layer.h>
23 #include <net/caif/cfcnfg.h>
24 #include <net/caif/cfpkt.h>
25 #include <net/caif/caif_dev.h>
26 
27 /* GPRS PDP connection has MTU to 1500 */
28 #define GPRS_PDP_MTU 1500
29 /* 5 sec. connect timeout */
30 #define CONNECT_TIMEOUT (5 * HZ)
31 #define CAIF_NET_DEFAULT_QUEUE_LEN 500
32 
33 /*This list is protected by the rtnl lock. */
34 static LIST_HEAD(chnl_net_list);
35 
36 MODULE_LICENSE("GPL");
37 MODULE_ALIAS_RTNL_LINK("caif");
38 
39 enum caif_states {
40 	CAIF_CONNECTED		= 1,
41 	CAIF_CONNECTING,
42 	CAIF_DISCONNECTED,
43 	CAIF_SHUTDOWN
44 };
45 
46 struct chnl_net {
47 	struct cflayer chnl;
48 	struct net_device_stats stats;
49 	struct caif_connect_request conn_req;
50 	struct list_head list_field;
51 	struct net_device *netdev;
52 	char name[256];
53 	wait_queue_head_t netmgmt_wq;
54 	/* Flow status to remember and control the transmission. */
55 	bool flowenabled;
56 	enum caif_states state;
57 };
58 
59 static void robust_list_del(struct list_head *delete_node)
60 {
61 	struct list_head *list_node;
62 	struct list_head *n;
63 	ASSERT_RTNL();
64 	list_for_each_safe(list_node, n, &chnl_net_list) {
65 		if (list_node == delete_node) {
66 			list_del(list_node);
67 			return;
68 		}
69 	}
70 	WARN_ON(1);
71 }
72 
73 static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)
74 {
75 	struct sk_buff *skb;
76 	struct chnl_net *priv  = container_of(layr, struct chnl_net, chnl);
77 	int pktlen;
78 	int err = 0;
79 
80 	priv = container_of(layr, struct chnl_net, chnl);
81 
82 	if (!priv)
83 		return -EINVAL;
84 
85 	/* Get length of CAIF packet. */
86 	pktlen = cfpkt_getlen(pkt);
87 
88 	skb = (struct sk_buff *) cfpkt_tonative(pkt);
89 	/* Pass some minimum information and
90 	 * send the packet to the net stack.
91 	 */
92 	skb->dev = priv->netdev;
93 	skb->protocol = htons(ETH_P_IP);
94 
95 	/* If we change the header in loop mode, the checksum is corrupted. */
96 	if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP)
97 		skb->ip_summed = CHECKSUM_UNNECESSARY;
98 	else
99 		skb->ip_summed = CHECKSUM_NONE;
100 
101 	if (in_interrupt())
102 		netif_rx(skb);
103 	else
104 		netif_rx_ni(skb);
105 
106 	/* Update statistics. */
107 	priv->netdev->stats.rx_packets++;
108 	priv->netdev->stats.rx_bytes += pktlen;
109 
110 	return err;
111 }
112 
113 static int delete_device(struct chnl_net *dev)
114 {
115 	ASSERT_RTNL();
116 	if (dev->netdev)
117 		unregister_netdevice(dev->netdev);
118 	return 0;
119 }
120 
121 static void close_work(struct work_struct *work)
122 {
123 	struct chnl_net *dev = NULL;
124 	struct list_head *list_node;
125 	struct list_head *_tmp;
126 	/* May be called with or without RTNL lock held */
127 	int islocked = rtnl_is_locked();
128 	if (!islocked)
129 		rtnl_lock();
130 	list_for_each_safe(list_node, _tmp, &chnl_net_list) {
131 		dev = list_entry(list_node, struct chnl_net, list_field);
132 		if (dev->state == CAIF_SHUTDOWN)
133 			dev_close(dev->netdev);
134 	}
135 	if (!islocked)
136 		rtnl_unlock();
137 }
138 static DECLARE_WORK(close_worker, close_work);
139 
140 static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow,
141 				int phyid)
142 {
143 	struct chnl_net *priv = container_of(layr, struct chnl_net, chnl);
144 	pr_debug("NET flowctrl func called flow: %s\n",
145 		flow == CAIF_CTRLCMD_FLOW_ON_IND ? "ON" :
146 		flow == CAIF_CTRLCMD_INIT_RSP ? "INIT" :
147 		flow == CAIF_CTRLCMD_FLOW_OFF_IND ? "OFF" :
148 		flow == CAIF_CTRLCMD_DEINIT_RSP ? "CLOSE/DEINIT" :
149 		flow == CAIF_CTRLCMD_INIT_FAIL_RSP ? "OPEN_FAIL" :
150 		flow == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND ?
151 		 "REMOTE_SHUTDOWN" : "UKNOWN CTRL COMMAND");
152 
153 
154 
155 	switch (flow) {
156 	case CAIF_CTRLCMD_FLOW_OFF_IND:
157 		priv->flowenabled = false;
158 		netif_stop_queue(priv->netdev);
159 		break;
160 	case CAIF_CTRLCMD_DEINIT_RSP:
161 		priv->state = CAIF_DISCONNECTED;
162 		break;
163 	case CAIF_CTRLCMD_INIT_FAIL_RSP:
164 		priv->state = CAIF_DISCONNECTED;
165 		wake_up_interruptible(&priv->netmgmt_wq);
166 		break;
167 	case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
168 		priv->state = CAIF_SHUTDOWN;
169 		netif_tx_disable(priv->netdev);
170 		schedule_work(&close_worker);
171 		break;
172 	case CAIF_CTRLCMD_FLOW_ON_IND:
173 		priv->flowenabled = true;
174 		netif_wake_queue(priv->netdev);
175 		break;
176 	case CAIF_CTRLCMD_INIT_RSP:
177 		priv->state = CAIF_CONNECTED;
178 		priv->flowenabled = true;
179 		netif_wake_queue(priv->netdev);
180 		wake_up_interruptible(&priv->netmgmt_wq);
181 		break;
182 	default:
183 		break;
184 	}
185 }
186 
187 static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
188 {
189 	struct chnl_net *priv;
190 	struct cfpkt *pkt = NULL;
191 	int len;
192 	int result = -1;
193 	/* Get our private data. */
194 	priv = netdev_priv(dev);
195 
196 	if (skb->len > priv->netdev->mtu) {
197 		pr_warn("Size of skb exceeded MTU\n");
198 		return -ENOSPC;
199 	}
200 
201 	if (!priv->flowenabled) {
202 		pr_debug("dropping packets flow off\n");
203 		return NETDEV_TX_BUSY;
204 	}
205 
206 	if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP)
207 		swap(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
208 
209 	/* Store original SKB length. */
210 	len = skb->len;
211 
212 	pkt = cfpkt_fromnative(CAIF_DIR_OUT, (void *) skb);
213 
214 	/* Send the packet down the stack. */
215 	result = priv->chnl.dn->transmit(priv->chnl.dn, pkt);
216 	if (result) {
217 		if (result == -EAGAIN)
218 			result = NETDEV_TX_BUSY;
219 		return result;
220 	}
221 
222 	/* Update statistics. */
223 	dev->stats.tx_packets++;
224 	dev->stats.tx_bytes += len;
225 
226 	return NETDEV_TX_OK;
227 }
228 
229 static int chnl_net_open(struct net_device *dev)
230 {
231 	struct chnl_net *priv = NULL;
232 	int result = -1;
233 	int llifindex, headroom, tailroom, mtu;
234 	struct net_device *lldev;
235 	ASSERT_RTNL();
236 	priv = netdev_priv(dev);
237 	if (!priv) {
238 		pr_debug("chnl_net_open: no priv\n");
239 		return -ENODEV;
240 	}
241 
242 	if (priv->state != CAIF_CONNECTING) {
243 		priv->state = CAIF_CONNECTING;
244 		result = caif_connect_client(&priv->conn_req, &priv->chnl,
245 					&llifindex, &headroom, &tailroom);
246 		if (result != 0) {
247 				pr_debug("err: "
248 					 "Unable to register and open device,"
249 					 " Err:%d\n",
250 					 result);
251 				goto error;
252 		}
253 
254 		lldev = dev_get_by_index(dev_net(dev), llifindex);
255 
256 		if (lldev == NULL) {
257 			pr_debug("no interface?\n");
258 			result = -ENODEV;
259 			goto error;
260 		}
261 
262 		dev->needed_tailroom = tailroom + lldev->needed_tailroom;
263 		dev->hard_header_len = headroom + lldev->hard_header_len +
264 			lldev->needed_tailroom;
265 
266 		/*
267 		 * MTU, head-room etc is not know before we have a
268 		 * CAIF link layer device available. MTU calculation may
269 		 * override initial RTNL configuration.
270 		 * MTU is minimum of current mtu, link layer mtu pluss
271 		 * CAIF head and tail, and PDP GPRS contexts max MTU.
272 		 */
273 		mtu = min_t(int, dev->mtu, lldev->mtu - (headroom + tailroom));
274 		mtu = min_t(int, GPRS_PDP_MTU, mtu);
275 		dev_set_mtu(dev, mtu);
276 		dev_put(lldev);
277 
278 		if (mtu < 100) {
279 			pr_warn("CAIF Interface MTU too small (%d)\n", mtu);
280 			result = -ENODEV;
281 			goto error;
282 		}
283 	}
284 
285 	rtnl_unlock();  /* Release RTNL lock during connect wait */
286 
287 	result = wait_event_interruptible_timeout(priv->netmgmt_wq,
288 						priv->state != CAIF_CONNECTING,
289 						CONNECT_TIMEOUT);
290 
291 	rtnl_lock();
292 
293 	if (result == -ERESTARTSYS) {
294 		pr_debug("wait_event_interruptible woken by a signal\n");
295 		result = -ERESTARTSYS;
296 		goto error;
297 	}
298 
299 	if (result == 0) {
300 		pr_debug("connect timeout\n");
301 		caif_disconnect_client(&priv->chnl);
302 		priv->state = CAIF_DISCONNECTED;
303 		pr_debug("state disconnected\n");
304 		result = -ETIMEDOUT;
305 		goto error;
306 	}
307 
308 	if (priv->state != CAIF_CONNECTED) {
309 		pr_debug("connect failed\n");
310 		result = -ECONNREFUSED;
311 		goto error;
312 	}
313 	pr_debug("CAIF Netdevice connected\n");
314 	return 0;
315 
316 error:
317 	caif_disconnect_client(&priv->chnl);
318 	priv->state = CAIF_DISCONNECTED;
319 	pr_debug("state disconnected\n");
320 	return result;
321 
322 }
323 
324 static int chnl_net_stop(struct net_device *dev)
325 {
326 	struct chnl_net *priv;
327 
328 	ASSERT_RTNL();
329 	priv = netdev_priv(dev);
330 	priv->state = CAIF_DISCONNECTED;
331 	caif_disconnect_client(&priv->chnl);
332 	return 0;
333 }
334 
335 static int chnl_net_init(struct net_device *dev)
336 {
337 	struct chnl_net *priv;
338 	ASSERT_RTNL();
339 	priv = netdev_priv(dev);
340 	strncpy(priv->name, dev->name, sizeof(priv->name));
341 	return 0;
342 }
343 
344 static void chnl_net_uninit(struct net_device *dev)
345 {
346 	struct chnl_net *priv;
347 	ASSERT_RTNL();
348 	priv = netdev_priv(dev);
349 	robust_list_del(&priv->list_field);
350 }
351 
352 static const struct net_device_ops netdev_ops = {
353 	.ndo_open = chnl_net_open,
354 	.ndo_stop = chnl_net_stop,
355 	.ndo_init = chnl_net_init,
356 	.ndo_uninit = chnl_net_uninit,
357 	.ndo_start_xmit = chnl_net_start_xmit,
358 };
359 
360 static void ipcaif_net_setup(struct net_device *dev)
361 {
362 	struct chnl_net *priv;
363 	dev->netdev_ops = &netdev_ops;
364 	dev->destructor = free_netdev;
365 	dev->flags |= IFF_NOARP;
366 	dev->flags |= IFF_POINTOPOINT;
367 	dev->mtu = GPRS_PDP_MTU;
368 	dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN;
369 
370 	priv = netdev_priv(dev);
371 	priv->chnl.receive = chnl_recv_cb;
372 	priv->chnl.ctrlcmd = chnl_flowctrl_cb;
373 	priv->netdev = dev;
374 	priv->conn_req.protocol = CAIFPROTO_DATAGRAM;
375 	priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW;
376 	priv->conn_req.priority = CAIF_PRIO_LOW;
377 	/* Insert illegal value */
378 	priv->conn_req.sockaddr.u.dgm.connection_id = -1;
379 	priv->flowenabled = false;
380 
381 	ASSERT_RTNL();
382 	init_waitqueue_head(&priv->netmgmt_wq);
383 	list_add(&priv->list_field, &chnl_net_list);
384 }
385 
386 
387 static int ipcaif_fill_info(struct sk_buff *skb, const struct net_device *dev)
388 {
389 	struct chnl_net *priv;
390 	u8 loop;
391 	priv = netdev_priv(dev);
392 	NLA_PUT_U32(skb, IFLA_CAIF_IPV4_CONNID,
393 		    priv->conn_req.sockaddr.u.dgm.connection_id);
394 	NLA_PUT_U32(skb, IFLA_CAIF_IPV6_CONNID,
395 		    priv->conn_req.sockaddr.u.dgm.connection_id);
396 	loop = priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP;
397 	NLA_PUT_U8(skb, IFLA_CAIF_LOOPBACK, loop);
398 
399 
400 	return 0;
401 nla_put_failure:
402 	return -EMSGSIZE;
403 
404 }
405 
406 static void caif_netlink_parms(struct nlattr *data[],
407 				struct caif_connect_request *conn_req)
408 {
409 	if (!data) {
410 		pr_warn("no params data found\n");
411 		return;
412 	}
413 	if (data[IFLA_CAIF_IPV4_CONNID])
414 		conn_req->sockaddr.u.dgm.connection_id =
415 			nla_get_u32(data[IFLA_CAIF_IPV4_CONNID]);
416 	if (data[IFLA_CAIF_IPV6_CONNID])
417 		conn_req->sockaddr.u.dgm.connection_id =
418 			nla_get_u32(data[IFLA_CAIF_IPV6_CONNID]);
419 	if (data[IFLA_CAIF_LOOPBACK]) {
420 		if (nla_get_u8(data[IFLA_CAIF_LOOPBACK]))
421 			conn_req->protocol = CAIFPROTO_DATAGRAM_LOOP;
422 		else
423 			conn_req->protocol = CAIFPROTO_DATAGRAM;
424 	}
425 }
426 
427 static int ipcaif_newlink(struct net *src_net, struct net_device *dev,
428 			  struct nlattr *tb[], struct nlattr *data[])
429 {
430 	int ret;
431 	struct chnl_net *caifdev;
432 	ASSERT_RTNL();
433 	caifdev = netdev_priv(dev);
434 	caif_netlink_parms(data, &caifdev->conn_req);
435 	dev_net_set(caifdev->netdev, src_net);
436 
437 	ret = register_netdevice(dev);
438 	if (ret)
439 		pr_warn("device rtml registration failed\n");
440 	return ret;
441 }
442 
443 static int ipcaif_changelink(struct net_device *dev, struct nlattr *tb[],
444 				struct nlattr *data[])
445 {
446 	struct chnl_net *caifdev;
447 	ASSERT_RTNL();
448 	caifdev = netdev_priv(dev);
449 	caif_netlink_parms(data, &caifdev->conn_req);
450 	netdev_state_change(dev);
451 	return 0;
452 }
453 
454 static size_t ipcaif_get_size(const struct net_device *dev)
455 {
456 	return
457 		/* IFLA_CAIF_IPV4_CONNID */
458 		nla_total_size(4) +
459 		/* IFLA_CAIF_IPV6_CONNID */
460 		nla_total_size(4) +
461 		/* IFLA_CAIF_LOOPBACK */
462 		nla_total_size(2) +
463 		0;
464 }
465 
466 static const struct nla_policy ipcaif_policy[IFLA_CAIF_MAX + 1] = {
467 	[IFLA_CAIF_IPV4_CONNID]	      = { .type = NLA_U32 },
468 	[IFLA_CAIF_IPV6_CONNID]	      = { .type = NLA_U32 },
469 	[IFLA_CAIF_LOOPBACK]	      = { .type = NLA_U8 }
470 };
471 
472 
473 static struct rtnl_link_ops ipcaif_link_ops __read_mostly = {
474 	.kind		= "caif",
475 	.priv_size	= sizeof(struct chnl_net),
476 	.setup		= ipcaif_net_setup,
477 	.maxtype	= IFLA_CAIF_MAX,
478 	.policy		= ipcaif_policy,
479 	.newlink	= ipcaif_newlink,
480 	.changelink	= ipcaif_changelink,
481 	.get_size	= ipcaif_get_size,
482 	.fill_info	= ipcaif_fill_info,
483 
484 };
485 
486 static int __init chnl_init_module(void)
487 {
488 	return rtnl_link_register(&ipcaif_link_ops);
489 }
490 
491 static void __exit chnl_exit_module(void)
492 {
493 	struct chnl_net *dev = NULL;
494 	struct list_head *list_node;
495 	struct list_head *_tmp;
496 	rtnl_link_unregister(&ipcaif_link_ops);
497 	rtnl_lock();
498 	list_for_each_safe(list_node, _tmp, &chnl_net_list) {
499 		dev = list_entry(list_node, struct chnl_net, list_field);
500 		list_del(list_node);
501 		delete_device(dev);
502 	}
503 	rtnl_unlock();
504 }
505 
506 module_init(chnl_init_module);
507 module_exit(chnl_exit_module);
508