blob: f82676d66f38204404c9b6f2a893963a7eaca676 [file] [log] [blame]
Conner Huff2357fa52017-02-03 11:19:02 -08001/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -06002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * RMNET Data configuration engine
13 */
14
15#include <net/sock.h>
16#include <linux/module.h>
17#include <linux/netlink.h>
18#include <linux/netdevice.h>
19#include <linux/skbuff.h>
20#include <linux/spinlock.h>
21#include <linux/rmnet_data.h>
22#include <net/rmnet_config.h>
23#include "rmnet_data_config.h"
24#include "rmnet_data_handlers.h"
25#include "rmnet_data_vnd.h"
26#include "rmnet_data_private.h"
27#include "rmnet_data_trace.h"
28
29RMNET_LOG_MODULE(RMNET_DATA_LOGMASK_CONFIG);
30
31/* Local Definitions and Declarations */
32static struct sock *nl_socket_handle;
33
34#ifndef RMNET_KERNEL_PRE_3_8
35static struct netlink_kernel_cfg rmnet_netlink_cfg = {
36 .input = rmnet_config_netlink_msg_handler
37};
38#endif
39
40static struct notifier_block rmnet_dev_notifier = {
41 .notifier_call = rmnet_config_notify_cb,
42 .next = 0,
43 .priority = 0
44};
45
46struct rmnet_free_vnd_work {
47 struct work_struct work;
48 int vnd_id[RMNET_DATA_MAX_VND];
49 int count;
50};
51
52/* Init and Cleanup */
53
54#ifdef RMNET_KERNEL_PRE_3_8
55static struct sock *_rmnet_config_start_netlink(void)
56{
57 return netlink_kernel_create(&init_net,
58 RMNET_NETLINK_PROTO,
59 0,
60 rmnet_config_netlink_msg_handler,
61 NULL,
62 THIS_MODULE);
63}
64#else
65static struct sock *_rmnet_config_start_netlink(void)
66{
67 return netlink_kernel_create(&init_net,
68 RMNET_NETLINK_PROTO,
69 &rmnet_netlink_cfg);
70}
71#endif /* RMNET_KERNEL_PRE_3_8 */
72
73/* rmnet_config_init() - Startup init
74 *
75 * Registers netlink protocol with kernel and opens socket. Netlink handler is
76 * registered with kernel.
77 */
78int rmnet_config_init(void)
79{
80 int rc;
81
82 nl_socket_handle = _rmnet_config_start_netlink();
83 if (!nl_socket_handle) {
84 LOGE("%s", "Failed to init netlink socket");
85 return RMNET_INIT_ERROR;
86 }
87
88 rc = register_netdevice_notifier(&rmnet_dev_notifier);
89 if (rc != 0) {
90 LOGE("Failed to register device notifier; rc=%d", rc);
91 /* TODO: Cleanup the nl socket */
92 return RMNET_INIT_ERROR;
93 }
94
95 return 0;
96}
97
98/* rmnet_config_exit() - Cleans up all netlink related resources */
99void rmnet_config_exit(void)
100{
101 int rc;
102
103 netlink_kernel_release(nl_socket_handle);
104 rc = unregister_netdevice_notifier(&rmnet_dev_notifier);
105 if (rc != 0)
106 LOGE("Failed to unregister device notifier; rc=%d", rc);
107}
108
109/* Helper Functions */
110
111/* _rmnet_is_physical_endpoint_associated() - Determines if device is associated
112 * @dev: Device to get check
113 *
114 * Compares device rx_handler callback pointer against known function
115 *
116 * Return:
117 * - 1 if associated
118 * - 0 if NOT associated
119 */
120static inline int _rmnet_is_physical_endpoint_associated(struct net_device *dev)
121{
122 rx_handler_func_t *rx_handler;
123
124 rx_handler = rcu_dereference(dev->rx_handler);
125
126 if (rx_handler == rmnet_rx_handler)
127 return 1;
128 else
129 return 0;
130}
131
132/* _rmnet_get_phys_ep_config() - Get physical ep config for an associated device
133 * @dev: Device to get endpoint configuration from
134 *
135 * Return:
136 * - pointer to configuration if successful
137 * - 0 (null) if device is not associated
138 */
139struct rmnet_phys_ep_config *_rmnet_get_phys_ep_config
140 (struct net_device *dev)
141{
142 struct rmnet_phys_ep_conf_s *_rmnet_phys_ep_config;
143
144 if (_rmnet_is_physical_endpoint_associated(dev)) {
145 _rmnet_phys_ep_config = (struct rmnet_phys_ep_conf_s *)
146 rcu_dereference(dev->rx_handler_data);
147 if (_rmnet_phys_ep_config && _rmnet_phys_ep_config->config)
148 return (struct rmnet_phys_ep_config *)
149 _rmnet_phys_ep_config->config;
150 else
151 return 0;
152 } else {
153 return 0;
154 }
155}
156
157/* _rmnet_get_logical_ep() - Gets the logical end point configuration
158 * structure for a network device
159 * @dev: Device to get endpoint configuration from
160 * @config_id: Logical endpoint id on device
161 * Retrieves the logical_endpoint_config structure.
162 *
163 * Return:
164 * - End point configuration structure
165 * - NULL in case of an error
166 */
167struct rmnet_logical_ep_conf_s *_rmnet_get_logical_ep(struct net_device *dev,
168 int config_id)
169{
170 struct rmnet_phys_ep_config *config;
171 struct rmnet_logical_ep_conf_s *epconfig_l;
172
173 if (rmnet_vnd_is_vnd(dev)) {
174 epconfig_l = rmnet_vnd_get_le_config(dev);
175 } else {
176 config = _rmnet_get_phys_ep_config(dev);
177
178 if (!config)
179 return NULL;
180
181 if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT)
182 epconfig_l = &config->local_ep;
183 else
184 epconfig_l = &config->muxed_ep[config_id];
185 }
186
187 return epconfig_l;
188}
189
190/* Netlink Handler */
191static void _rmnet_netlink_set_link_egress_data_format
192 (struct rmnet_nl_msg_s *rmnet_header,
193 struct rmnet_nl_msg_s *resp_rmnet)
194{
195 struct net_device *dev;
196
197 if (!rmnet_header || !resp_rmnet)
198 return;
199
200 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
201 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
202
203 if (!dev) {
204 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
205 return;
206 }
207
208 resp_rmnet->return_code =
209 rmnet_set_egress_data_format(dev,
210 rmnet_header->data_format.flags,
211 rmnet_header->data_format.agg_size,
212 rmnet_header->data_format.agg_count
213 );
214 dev_put(dev);
215}
216
217static void _rmnet_netlink_set_link_ingress_data_format
218 (struct rmnet_nl_msg_s *rmnet_header,
219 struct rmnet_nl_msg_s *resp_rmnet)
220{
221 struct net_device *dev;
222
223 if (!rmnet_header || !resp_rmnet)
224 return;
225
226 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
227
228 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
229 if (!dev) {
230 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
231 return;
232 }
233
234 resp_rmnet->return_code = rmnet_set_ingress_data_format(
235 dev,
236 rmnet_header->data_format.flags,
237 rmnet_header->data_format.tail_spacing);
238 dev_put(dev);
239}
240
241static void _rmnet_netlink_set_logical_ep_config
242 (struct rmnet_nl_msg_s *rmnet_header,
243 struct rmnet_nl_msg_s *resp_rmnet)
244{
245 struct net_device *dev, *dev2;
246
247 if (!rmnet_header || !resp_rmnet)
248 return;
249
250 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
251 if (rmnet_header->local_ep_config.ep_id < -1 ||
252 rmnet_header->local_ep_config.ep_id > 254) {
253 resp_rmnet->return_code = RMNET_CONFIG_BAD_ARGUMENTS;
254 return;
255 }
256
257 dev = dev_get_by_name(&init_net,
258 rmnet_header->local_ep_config.dev);
259
260 dev2 = dev_get_by_name(&init_net,
261 rmnet_header->local_ep_config.next_dev);
262
263 if (dev && dev2)
264 resp_rmnet->return_code =
265 rmnet_set_logical_endpoint_config(
266 dev,
267 rmnet_header->local_ep_config.ep_id,
268 rmnet_header->local_ep_config.operating_mode,
269 dev2);
270 else
271 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
272
273 if (dev)
274 dev_put(dev);
275 if (dev2)
276 dev_put(dev2);
277}
278
279static void _rmnet_netlink_unset_logical_ep_config
280 (struct rmnet_nl_msg_s *rmnet_header,
281 struct rmnet_nl_msg_s *resp_rmnet)
282{
283 struct net_device *dev;
284
285 if (!rmnet_header || !resp_rmnet)
286 return;
287
288 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
289 if (rmnet_header->local_ep_config.ep_id < -1 ||
290 rmnet_header->local_ep_config.ep_id > 254) {
291 resp_rmnet->return_code = RMNET_CONFIG_BAD_ARGUMENTS;
292 return;
293 }
294
295 dev = dev_get_by_name(&init_net,
296 rmnet_header->local_ep_config.dev);
297
298 if (dev) {
299 resp_rmnet->return_code =
300 rmnet_unset_logical_endpoint_config(
301 dev,
302 rmnet_header->local_ep_config.ep_id);
303 dev_put(dev);
304 } else {
305 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
306 }
307}
308
309static void _rmnet_netlink_get_logical_ep_config
310 (struct rmnet_nl_msg_s *rmnet_header,
311 struct rmnet_nl_msg_s *resp_rmnet)
312{
313 struct net_device *dev;
314
315 if (!rmnet_header || !resp_rmnet)
316 return;
317
318 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
319 if (rmnet_header->local_ep_config.ep_id < -1 ||
320 rmnet_header->local_ep_config.ep_id > 254) {
321 resp_rmnet->return_code = RMNET_CONFIG_BAD_ARGUMENTS;
322 return;
323 }
324
325 dev = dev_get_by_name(&init_net,
326 rmnet_header->local_ep_config.dev);
327
328 if (dev)
329 resp_rmnet->return_code =
330 rmnet_get_logical_endpoint_config(
331 dev,
332 rmnet_header->local_ep_config.ep_id,
333 &resp_rmnet->local_ep_config.operating_mode,
334 resp_rmnet->local_ep_config.next_dev,
335 sizeof(resp_rmnet->local_ep_config.next_dev));
336 else {
337 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
338 return;
339 }
340
341 if (resp_rmnet->return_code == RMNET_CONFIG_OK) {
342 /* Begin Data */
343 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
344 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)
345 ->local_ep_config);
346 }
347 dev_put(dev);
348}
349
350static void _rmnet_netlink_associate_network_device
351 (struct rmnet_nl_msg_s *rmnet_header,
352 struct rmnet_nl_msg_s *resp_rmnet)
353{
354 struct net_device *dev;
355
356 if (!rmnet_header || !resp_rmnet)
357 return;
358
359 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
360
361 dev = dev_get_by_name(&init_net, rmnet_header->data);
362 if (!dev) {
363 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
364 return;
365 }
366
367 resp_rmnet->return_code = rmnet_associate_network_device(dev);
368 dev_put(dev);
369}
370
371static void _rmnet_netlink_unassociate_network_device
372 (struct rmnet_nl_msg_s *rmnet_header,
373 struct rmnet_nl_msg_s *resp_rmnet)
374{
375 struct net_device *dev;
376
377 if (!rmnet_header || !resp_rmnet)
378 return;
379
380 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
381
382 dev = dev_get_by_name(&init_net, rmnet_header->data);
383 if (!dev) {
384 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
385 return;
386 }
387
388 resp_rmnet->return_code = rmnet_unassociate_network_device(dev);
389 dev_put(dev);
390}
391
392static void _rmnet_netlink_get_network_device_associated
393 (struct rmnet_nl_msg_s *rmnet_header,
394 struct rmnet_nl_msg_s *resp_rmnet)
395{
396 struct net_device *dev;
397
398 if (!rmnet_header || !resp_rmnet)
399 return;
400
401 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
402
403 dev = dev_get_by_name(&init_net, rmnet_header->data);
404 if (!dev) {
405 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
406 return;
407 }
408
409 resp_rmnet->return_code = _rmnet_is_physical_endpoint_associated(dev);
410 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
411 dev_put(dev);
412}
413
414static void _rmnet_netlink_get_link_egress_data_format
415 (struct rmnet_nl_msg_s *rmnet_header,
416 struct rmnet_nl_msg_s *resp_rmnet)
417{
418 struct net_device *dev;
419 struct rmnet_phys_ep_config *config;
420
421 if (!rmnet_header || !resp_rmnet)
422 return;
423
424 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
425
426 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
427 if (!dev) {
428 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
429 return;
430 }
431
432 config = _rmnet_get_phys_ep_config(dev);
433 if (!config) {
434 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
435 dev_put(dev);
436 return;
437 }
438
439 /* Begin Data */
440 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
441 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)
442 ->data_format);
443 resp_rmnet->data_format.flags = config->egress_data_format;
444 resp_rmnet->data_format.agg_count = config->egress_agg_count;
445 resp_rmnet->data_format.agg_size = config->egress_agg_size;
446 dev_put(dev);
447}
448
449static void _rmnet_netlink_get_link_ingress_data_format
450 (struct rmnet_nl_msg_s *rmnet_header,
451 struct rmnet_nl_msg_s *resp_rmnet)
452{
453 struct net_device *dev;
454 struct rmnet_phys_ep_config *config;
455
456 if (!rmnet_header || !resp_rmnet)
457 return;
458
459 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
460
461 dev = dev_get_by_name(&init_net, rmnet_header->data_format.dev);
462 if (!dev) {
463 resp_rmnet->return_code = RMNET_CONFIG_NO_SUCH_DEVICE;
464 return;
465 }
466
467 config = _rmnet_get_phys_ep_config(dev);
468 if (!config) {
469 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
470 dev_put(dev);
471 return;
472 }
473
474 /* Begin Data */
475 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
476 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)
477 ->data_format);
478 resp_rmnet->data_format.flags = config->ingress_data_format;
479 resp_rmnet->data_format.tail_spacing = config->tail_spacing;
480 dev_put(dev);
481}
482
483static void _rmnet_netlink_get_vnd_name
484 (struct rmnet_nl_msg_s *rmnet_header,
485 struct rmnet_nl_msg_s *resp_rmnet)
486{
487 int r;
488
489 if (!rmnet_header || !resp_rmnet)
490 return;
491
492 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
493
494 r = rmnet_vnd_get_name(rmnet_header->vnd.id, resp_rmnet->vnd.vnd_name,
495 RMNET_MAX_STR_LEN);
496
497 if (r != 0) {
498 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
499 return;
500 }
501
502 /* Begin Data */
503 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNDATA;
504 resp_rmnet->arg_length = sizeof(((struct rmnet_nl_msg_s *)0)->vnd);
505}
506
507static void _rmnet_netlink_add_del_vnd_tc_flow
508 (u32 command,
509 struct rmnet_nl_msg_s *rmnet_header,
510 struct rmnet_nl_msg_s *resp_rmnet)
511{
512 u32 id;
513 u32 map_flow_id;
514 u32 tc_flow_id;
515
516 if (!rmnet_header || !resp_rmnet)
517 return;
518
519 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
520
521 id = rmnet_header->flow_control.id;
522 map_flow_id = rmnet_header->flow_control.map_flow_id;
523 tc_flow_id = rmnet_header->flow_control.tc_flow_id;
524
525 switch (command) {
526 case RMNET_NETLINK_ADD_VND_TC_FLOW:
527 resp_rmnet->return_code = rmnet_vnd_add_tc_flow(id,
528 map_flow_id,
529 tc_flow_id);
530 break;
531 case RMNET_NETLINK_DEL_VND_TC_FLOW:
532 resp_rmnet->return_code = rmnet_vnd_del_tc_flow(id,
533 map_flow_id,
534 tc_flow_id);
535 break;
536 default:
537 LOGM("Called with unhandled command %d", command);
538 resp_rmnet->return_code = RMNET_CONFIG_INVALID_REQUEST;
539 break;
540 }
541}
542
543/* rmnet_config_netlink_msg_handler() - Netlink message handler callback
544 * @skb: Packet containing netlink messages
545 *
546 * Standard kernel-expected format for a netlink message handler. Processes SKBs
547 * which contain RmNet data specific netlink messages.
548 */
549void rmnet_config_netlink_msg_handler(struct sk_buff *skb)
550{
551 struct nlmsghdr *nlmsg_header, *resp_nlmsg;
552 struct rmnet_nl_msg_s *rmnet_header, *resp_rmnet;
553 int return_pid, response_data_length;
554 struct sk_buff *skb_response;
555
556 response_data_length = 0;
557 nlmsg_header = (struct nlmsghdr *)skb->data;
558 rmnet_header = (struct rmnet_nl_msg_s *)nlmsg_data(nlmsg_header);
559
Conner Huff2357fa52017-02-03 11:19:02 -0800560 if (!nlmsg_header->nlmsg_pid ||
561 (nlmsg_header->nlmsg_len < sizeof(struct nlmsghdr) +
562 sizeof(struct rmnet_nl_msg_s)))
563 return;
564
Subash Abhinov Kasiviswanathan2139ce8a2016-10-14 11:01:48 -0600565 LOGL("Netlink message pid=%d, seq=%d, length=%d, rmnet_type=%d",
566 nlmsg_header->nlmsg_pid,
567 nlmsg_header->nlmsg_seq,
568 nlmsg_header->nlmsg_len,
569 rmnet_header->message_type);
570
571 return_pid = nlmsg_header->nlmsg_pid;
572
573 skb_response = nlmsg_new(sizeof(struct nlmsghdr)
574 + sizeof(struct rmnet_nl_msg_s),
575 GFP_KERNEL);
576
577 if (!skb_response) {
578 LOGH("%s", "Failed to allocate response buffer");
579 return;
580 }
581
582 resp_nlmsg = nlmsg_put(skb_response,
583 0,
584 nlmsg_header->nlmsg_seq,
585 NLMSG_DONE,
586 sizeof(struct rmnet_nl_msg_s),
587 0);
588
589 resp_rmnet = nlmsg_data(resp_nlmsg);
590
591 if (!resp_rmnet)
592 return;
593
594 resp_rmnet->message_type = rmnet_header->message_type;
595 rtnl_lock();
596 switch (rmnet_header->message_type) {
597 case RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE:
598 _rmnet_netlink_associate_network_device
599 (rmnet_header, resp_rmnet);
600 break;
601
602 case RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE:
603 _rmnet_netlink_unassociate_network_device
604 (rmnet_header, resp_rmnet);
605 break;
606
607 case RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED:
608 _rmnet_netlink_get_network_device_associated
609 (rmnet_header, resp_rmnet);
610 break;
611
612 case RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT:
613 _rmnet_netlink_set_link_egress_data_format
614 (rmnet_header, resp_rmnet);
615 break;
616
617 case RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT:
618 _rmnet_netlink_get_link_egress_data_format
619 (rmnet_header, resp_rmnet);
620 break;
621
622 case RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT:
623 _rmnet_netlink_set_link_ingress_data_format
624 (rmnet_header, resp_rmnet);
625 break;
626
627 case RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT:
628 _rmnet_netlink_get_link_ingress_data_format
629 (rmnet_header, resp_rmnet);
630 break;
631
632 case RMNET_NETLINK_SET_LOGICAL_EP_CONFIG:
633 _rmnet_netlink_set_logical_ep_config(rmnet_header, resp_rmnet);
634 break;
635
636 case RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG:
637 _rmnet_netlink_unset_logical_ep_config(rmnet_header,
638 resp_rmnet);
639 break;
640
641 case RMNET_NETLINK_GET_LOGICAL_EP_CONFIG:
642 _rmnet_netlink_get_logical_ep_config(rmnet_header, resp_rmnet);
643 break;
644
645 case RMNET_NETLINK_NEW_VND:
646 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
647 resp_rmnet->return_code =
648 rmnet_create_vnd(rmnet_header->vnd.id);
649 break;
650
651 case RMNET_NETLINK_NEW_VND_WITH_PREFIX:
652 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
653 resp_rmnet->return_code = rmnet_create_vnd_prefix(
654 rmnet_header->vnd.id,
655 rmnet_header->vnd.vnd_name);
656 break;
657
658 case RMNET_NETLINK_FREE_VND:
659 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
660 /* Please check rmnet_vnd_free_dev documentation regarding
661 * the below locking sequence
662 */
663 rtnl_unlock();
664 resp_rmnet->return_code = rmnet_free_vnd(rmnet_header->vnd.id);
665 rtnl_lock();
666 break;
667
668 case RMNET_NETLINK_GET_VND_NAME:
669 _rmnet_netlink_get_vnd_name(rmnet_header, resp_rmnet);
670 break;
671
672 case RMNET_NETLINK_DEL_VND_TC_FLOW:
673 case RMNET_NETLINK_ADD_VND_TC_FLOW:
674 _rmnet_netlink_add_del_vnd_tc_flow(rmnet_header->message_type,
675 rmnet_header,
676 resp_rmnet);
677 break;
678
679 default:
680 resp_rmnet->crd = RMNET_NETLINK_MSG_RETURNCODE;
681 resp_rmnet->return_code = RMNET_CONFIG_UNKNOWN_MESSAGE;
682 break;
683 }
684 rtnl_unlock();
685 nlmsg_unicast(nl_socket_handle, skb_response, return_pid);
686 LOGD("%s", "Done processing command");
687}
688
689/* Configuration API */
690
691/* rmnet_unassociate_network_device() - Unassociate network device
692 * @dev: Device to unassociate
693 *
694 * Frees all structures generate for device. Unregisters rx_handler
695 * todo: needs to do some sanity verification first (is device in use, etc...)
696 *
697 * Return:
698 * - RMNET_CONFIG_OK if successful
699 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
700 * - RMNET_CONFIG_INVALID_REQUEST if device is not already associated
701 * - RMNET_CONFIG_DEVICE_IN_USE if device has logical ep that wasn't unset
702 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
703 */
704int rmnet_unassociate_network_device(struct net_device *dev)
705{
706 struct rmnet_phys_ep_conf_s *config;
707 int config_id = RMNET_LOCAL_LOGICAL_ENDPOINT;
708 struct rmnet_logical_ep_conf_s *epconfig_l;
709
710 ASSERT_RTNL();
711
712 LOGL("(%s);", dev->name);
713
714 if (!dev)
715 return RMNET_CONFIG_NO_SUCH_DEVICE;
716
717 if (!_rmnet_is_physical_endpoint_associated(dev))
718 return RMNET_CONFIG_INVALID_REQUEST;
719
720 for (; config_id < RMNET_DATA_MAX_LOGICAL_EP; config_id++) {
721 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
722 if (epconfig_l && epconfig_l->refcount)
723 return RMNET_CONFIG_DEVICE_IN_USE;
724 }
725
726 config = (struct rmnet_phys_ep_conf_s *)
727 rcu_dereference(dev->rx_handler_data);
728
729 if (!config)
730 return RMNET_CONFIG_UNKNOWN_ERROR;
731
732 kfree(config);
733
734 netdev_rx_handler_unregister(dev);
735
736 /* Explicitly release the reference from the device */
737 dev_put(dev);
738 trace_rmnet_unassociate(dev);
739 return RMNET_CONFIG_OK;
740}
741
742/* rmnet_set_ingress_data_format() - Set ingress data format on network device
743 * @dev: Device to ingress data format on
744 * @egress_data_format: 32-bit unsigned bitmask of ingress format
745 *
746 * Network device must already have association with RmNet Data driver
747 *
748 * Return:
749 * - RMNET_CONFIG_OK if successful
750 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
751 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
752 */
753int rmnet_set_ingress_data_format(struct net_device *dev,
754 u32 ingress_data_format,
755 uint8_t tail_spacing)
756{
757 struct rmnet_phys_ep_config *config;
758
759 ASSERT_RTNL();
760
761 LOGL("(%s,0x%08X);", dev->name, ingress_data_format);
762
763 if (!dev)
764 return RMNET_CONFIG_NO_SUCH_DEVICE;
765
766 config = _rmnet_get_phys_ep_config(dev);
767
768 if (!config)
769 return RMNET_CONFIG_INVALID_REQUEST;
770
771 config->ingress_data_format = ingress_data_format;
772 config->tail_spacing = tail_spacing;
773
774 return RMNET_CONFIG_OK;
775}
776
777/* rmnet_set_egress_data_format() - Set egress data format on network device
778 * @dev: Device to egress data format on
779 * @egress_data_format: 32-bit unsigned bitmask of egress format
780 *
781 * Network device must already have association with RmNet Data driver
782 * todo: Bounds check on agg_*
783 *
784 * Return:
785 * - RMNET_CONFIG_OK if successful
786 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
787 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
788 */
789int rmnet_set_egress_data_format(struct net_device *dev,
790 u32 egress_data_format,
791 u16 agg_size,
792 u16 agg_count)
793{
794 struct rmnet_phys_ep_config *config;
795
796 ASSERT_RTNL();
797
798 LOGL("(%s,0x%08X, %d, %d);",
799 dev->name, egress_data_format, agg_size, agg_count);
800
801 if (!dev)
802 return RMNET_CONFIG_NO_SUCH_DEVICE;
803
804 config = _rmnet_get_phys_ep_config(dev);
805
806 if (!config)
807 return RMNET_CONFIG_UNKNOWN_ERROR;
808
809 config->egress_data_format = egress_data_format;
810 config->egress_agg_size = agg_size;
811 config->egress_agg_count = agg_count;
812
813 return RMNET_CONFIG_OK;
814}
815
816/* rmnet_associate_network_device() - Associate network device
817 * @dev: Device to register with RmNet data
818 *
819 * Typically used on physical network devices. Registers RX handler and private
820 * metadata structures.
821 *
822 * Return:
823 * - RMNET_CONFIG_OK if successful
824 * - RMNET_CONFIG_NO_SUCH_DEVICE dev is null
825 * - RMNET_CONFIG_INVALID_REQUEST if the device to be associated is a vnd
826 * - RMNET_CONFIG_DEVICE_IN_USE if dev rx_handler is already filled
827 * - RMNET_CONFIG_DEVICE_IN_USE if netdev_rx_handler_register() fails
828 */
829int rmnet_associate_network_device(struct net_device *dev)
830{
831 struct rmnet_phys_ep_conf_s *config;
832 struct rmnet_phys_ep_config *conf;
833 int rc;
834
835 ASSERT_RTNL();
836
837 LOGL("(%s);\n", dev->name);
838
839 if (!dev)
840 return RMNET_CONFIG_NO_SUCH_DEVICE;
841
842 if (_rmnet_is_physical_endpoint_associated(dev)) {
843 LOGM("%s is already regestered", dev->name);
844 return RMNET_CONFIG_DEVICE_IN_USE;
845 }
846
847 if (rmnet_vnd_is_vnd(dev)) {
848 LOGM("%s is a vnd", dev->name);
849 return RMNET_CONFIG_INVALID_REQUEST;
850 }
851
852 config = kmalloc(sizeof(*config), GFP_ATOMIC);
853 conf = kmalloc(sizeof(*conf), GFP_ATOMIC);
854
855 if (!config || !conf)
856 return RMNET_CONFIG_NOMEM;
857
858 memset(config, 0, sizeof(struct rmnet_phys_ep_conf_s));
859 memset(conf, 0, sizeof(struct rmnet_phys_ep_config));
860
861 config->config = conf;
862 conf->dev = dev;
863 spin_lock_init(&conf->agg_lock);
864 config->recycle = kfree_skb;
865
866 rc = netdev_rx_handler_register(dev, rmnet_rx_handler, config);
867
868 if (rc) {
869 LOGM("netdev_rx_handler_register returns %d", rc);
870 kfree(config);
871 kfree(conf);
872 return RMNET_CONFIG_DEVICE_IN_USE;
873 }
874
875 /* Explicitly hold a reference to the device */
876 dev_hold(dev);
877 trace_rmnet_associate(dev);
878 return RMNET_CONFIG_OK;
879}
880
881/* _rmnet_set_logical_endpoint_config() - Set logical endpoing config on device
882 * @dev: Device to set endpoint configuration on
883 * @config_id: logical endpoint id on device
884 * @epconfig: endpoing configuration structure to set
885 *
886 * Return:
887 * - RMNET_CONFIG_OK if successful
888 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
889 * - RMNET_CONFIG_NO_SUCH_DEVICE if device to set config on is null
890 * - RMNET_CONFIG_DEVICE_IN_USE if device already has a logical ep
891 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
892 */
893int _rmnet_set_logical_endpoint_config(struct net_device *dev,
894 int config_id,
895 struct rmnet_logical_ep_conf_s *epconfig)
896{
897 struct rmnet_logical_ep_conf_s *epconfig_l;
898
899 ASSERT_RTNL();
900
901 if (!dev)
902 return RMNET_CONFIG_NO_SUCH_DEVICE;
903
904 if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
905 config_id >= RMNET_DATA_MAX_LOGICAL_EP)
906 return RMNET_CONFIG_BAD_ARGUMENTS;
907
908 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
909
910 if (!epconfig_l)
911 return RMNET_CONFIG_UNKNOWN_ERROR;
912
913 if (epconfig_l->refcount)
914 return RMNET_CONFIG_DEVICE_IN_USE;
915
916 memcpy(epconfig_l, epconfig, sizeof(struct rmnet_logical_ep_conf_s));
917 if (config_id == RMNET_LOCAL_LOGICAL_ENDPOINT)
918 epconfig_l->mux_id = 0;
919 else
920 epconfig_l->mux_id = config_id;
921
922 /* Explicitly hold a reference to the egress device */
923 dev_hold(epconfig_l->egress_dev);
924 return RMNET_CONFIG_OK;
925}
926
927/* _rmnet_unset_logical_endpoint_config() - Un-set the logical endpoing config
928 * on device
929 * @dev: Device to set endpoint configuration on
930 * @config_id: logical endpoint id on device
931 *
932 * Return:
933 * - RMNET_CONFIG_OK if successful
934 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
935 * - RMNET_CONFIG_NO_SUCH_DEVICE if device to set config on is null
936 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
937 */
938int _rmnet_unset_logical_endpoint_config(struct net_device *dev,
939 int config_id)
940{
941 struct rmnet_logical_ep_conf_s *epconfig_l = 0;
942
943 ASSERT_RTNL();
944
945 if (!dev)
946 return RMNET_CONFIG_NO_SUCH_DEVICE;
947
948 if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
949 config_id >= RMNET_DATA_MAX_LOGICAL_EP)
950 return RMNET_CONFIG_BAD_ARGUMENTS;
951
952 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
953
954 if (!epconfig_l || !epconfig_l->refcount)
955 return RMNET_CONFIG_NO_SUCH_DEVICE;
956
957 /* Explicitly release the reference from the egress device */
958 dev_put(epconfig_l->egress_dev);
959 memset(epconfig_l, 0, sizeof(struct rmnet_logical_ep_conf_s));
960
961 return RMNET_CONFIG_OK;
962}
963
964/* rmnet_set_logical_endpoint_config() - Set logical endpoint config on a device
965 * @dev: Device to set endpoint configuration on
966 * @config_id: logical endpoint id on device
967 * @rmnet_mode: endpoint mode. Values from: rmnet_config_endpoint_modes_e
968 * @egress_device: device node to forward packet to once done processing in
969 * ingress/egress handlers
970 *
971 * Creates a logical_endpoint_config structure and fills in the information from
972 * function arguments. Calls _rmnet_set_logical_endpoint_config() to finish
973 * configuration. Network device must already have association with RmNet Data
974 * driver
975 *
976 * Return:
977 * - RMNET_CONFIG_OK if successful
978 * - RMNET_CONFIG_BAD_EGRESS_DEVICE if egress device is null
979 * - RMNET_CONFIG_BAD_EGRESS_DEVICE if egress device is not handled by
980 * RmNet data module
981 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
982 * - RMNET_CONFIG_NO_SUCH_DEVICE if device to set config on is null
983 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
984 */
985int rmnet_set_logical_endpoint_config(struct net_device *dev,
986 int config_id,
987 u8 rmnet_mode,
988 struct net_device *egress_dev)
989{
990 struct rmnet_logical_ep_conf_s epconfig;
991
992 LOGL("(%s, %d, %d, %s);",
993 dev->name, config_id, rmnet_mode, egress_dev->name);
994
995 if (!egress_dev ||
996 ((!_rmnet_is_physical_endpoint_associated(egress_dev)) &&
997 (!rmnet_vnd_is_vnd(egress_dev)))) {
998 return RMNET_CONFIG_BAD_EGRESS_DEVICE;
999 }
1000
1001 memset(&epconfig, 0, sizeof(struct rmnet_logical_ep_conf_s));
1002 epconfig.refcount = 1;
1003 epconfig.rmnet_mode = rmnet_mode;
1004 epconfig.egress_dev = egress_dev;
1005
1006 return _rmnet_set_logical_endpoint_config(dev, config_id, &epconfig);
1007}
1008
1009/* rmnet_unset_logical_endpoint_config() - Un-set logical endpoing configuration
1010 * on a device
1011 * @dev: Device to set endpoint configuration on
1012 * @config_id: logical endpoint id on device
1013 *
1014 * Retrieves the logical_endpoint_config structure and frees the egress device.
1015 * Network device must already have association with RmNet Data driver
1016 *
1017 * Return:
1018 * - RMNET_CONFIG_OK if successful
1019 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
1020 * - RMNET_CONFIG_NO_SUCH_DEVICE device is not associated
1021 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range
1022 */
1023int rmnet_unset_logical_endpoint_config(struct net_device *dev,
1024 int config_id)
1025{
1026 LOGL("(%s, %d);", dev->name, config_id);
1027
1028 if (!dev || ((!_rmnet_is_physical_endpoint_associated(dev)) &&
1029 (!rmnet_vnd_is_vnd(dev)))) {
1030 return RMNET_CONFIG_NO_SUCH_DEVICE;
1031 }
1032
1033 return _rmnet_unset_logical_endpoint_config(dev, config_id);
1034}
1035
1036/* rmnet_get_logical_endpoint_config() - Gets logical endpoing configuration
1037 * for a device
1038 * @dev: Device to get endpoint configuration on
1039 * @config_id: logical endpoint id on device
1040 * @rmnet_mode: (I/O) logical endpoint mode
1041 * @egress_dev_name: (I/O) logical endpoint egress device name
1042 * @egress_dev_name_size: The maximal size of the I/O egress_dev_name
1043 *
1044 * Retrieves the logical_endpoint_config structure.
1045 * Network device must already have association with RmNet Data driver
1046 *
1047 * Return:
1048 * - RMNET_CONFIG_OK if successful
1049 * - RMNET_CONFIG_UNKNOWN_ERROR net_device private section is null
1050 * - RMNET_CONFIG_NO_SUCH_DEVICE device is not associated
1051 * - RMNET_CONFIG_BAD_ARGUMENTS if logical endpoint id is out of range or
1052 * if the provided buffer size for egress dev name is too short
1053 */
1054int rmnet_get_logical_endpoint_config(struct net_device *dev,
1055 int config_id,
1056 u8 *rmnet_mode,
1057 u8 *egress_dev_name,
1058 size_t egress_dev_name_size)
1059{
1060 struct rmnet_logical_ep_conf_s *epconfig_l = 0;
1061 size_t strlcpy_res = 0;
1062
1063 LOGL("(%s, %d);", dev->name, config_id);
1064
1065 if (!egress_dev_name || !rmnet_mode)
1066 return RMNET_CONFIG_BAD_ARGUMENTS;
1067 if (config_id < RMNET_LOCAL_LOGICAL_ENDPOINT ||
1068 config_id >= RMNET_DATA_MAX_LOGICAL_EP)
1069 return RMNET_CONFIG_BAD_ARGUMENTS;
1070
1071 epconfig_l = _rmnet_get_logical_ep(dev, config_id);
1072
1073 if (!epconfig_l || !epconfig_l->refcount)
1074 return RMNET_CONFIG_NO_SUCH_DEVICE;
1075
1076 *rmnet_mode = epconfig_l->rmnet_mode;
1077
1078 strlcpy_res = strlcpy(egress_dev_name, epconfig_l->egress_dev->name,
1079 egress_dev_name_size);
1080
1081 if (strlcpy_res >= egress_dev_name_size)
1082 return RMNET_CONFIG_BAD_ARGUMENTS;
1083
1084 return RMNET_CONFIG_OK;
1085}
1086
1087/* rmnet_create_vnd() - Create virtual network device node
1088 * @id: RmNet virtual device node id
1089 *
1090 * Return:
1091 * - result of rmnet_vnd_create_dev()
1092 */
1093int rmnet_create_vnd(int id)
1094{
1095 struct net_device *dev;
1096
1097 ASSERT_RTNL();
1098 LOGL("(%d);", id);
1099 return rmnet_vnd_create_dev(id, &dev, NULL);
1100}
1101
1102/* rmnet_create_vnd() - Create virtual network device node
1103 * @id: RmNet virtual device node id
1104 * @prefix: String prefix for device name
1105 *
1106 * Return:
1107 * - result of rmnet_vnd_create_dev()
1108 */
1109int rmnet_create_vnd_prefix(int id, const char *prefix)
1110{
1111 struct net_device *dev;
1112
1113 ASSERT_RTNL();
1114 LOGL("(%d, \"%s\");", id, prefix);
1115 return rmnet_vnd_create_dev(id, &dev, prefix);
1116}
1117
1118/* rmnet_free_vnd() - Free virtual network device node
1119 * @id: RmNet virtual device node id
1120 *
1121 * Return:
1122 * - result of rmnet_vnd_free_dev()
1123 */
1124int rmnet_free_vnd(int id)
1125{
1126 LOGL("(%d);", id);
1127 return rmnet_vnd_free_dev(id);
1128}
1129
1130static void _rmnet_free_vnd_later(struct work_struct *work)
1131{
1132 int i;
1133 struct rmnet_free_vnd_work *fwork;
1134
1135 fwork = container_of(work, struct rmnet_free_vnd_work, work);
1136
1137 for (i = 0; i < fwork->count; i++)
1138 rmnet_free_vnd(fwork->vnd_id[i]);
1139 kfree(fwork);
1140}
1141
1142/* rmnet_force_unassociate_device() - Force a device to unassociate
1143 * @dev: Device to unassociate
1144 *
1145 * Return:
1146 * - void
1147 */
1148static void rmnet_force_unassociate_device(struct net_device *dev)
1149{
1150 int i, j;
1151 struct net_device *vndev;
1152 struct rmnet_logical_ep_conf_s *cfg;
1153 struct rmnet_free_vnd_work *vnd_work;
1154
1155 ASSERT_RTNL();
1156
1157 if (!dev)
1158 return;
1159
1160 if (!_rmnet_is_physical_endpoint_associated(dev)) {
1161 LOGM("%s", "Called on unassociated device, skipping");
1162 return;
1163 }
1164
1165 trace_rmnet_unregister_cb_clear_vnds(dev);
1166 vnd_work = kmalloc(sizeof(*vnd_work), GFP_KERNEL);
1167 if (!vnd_work) {
1168 LOGH("%s", "Out of Memory");
1169 return;
1170 }
1171 INIT_WORK(&vnd_work->work, _rmnet_free_vnd_later);
1172 vnd_work->count = 0;
1173
1174 /* Check the VNDs for offending mappings */
1175 for (i = 0, j = 0; i < RMNET_DATA_MAX_VND &&
1176 j < RMNET_DATA_MAX_VND; i++) {
1177 vndev = rmnet_vnd_get_by_id(i);
1178 if (!vndev) {
1179 LOGL("VND %d not in use; skipping", i);
1180 continue;
1181 }
1182 cfg = rmnet_vnd_get_le_config(vndev);
1183 if (!cfg) {
1184 LOGH("Got NULL config from VND %d", i);
1185 continue;
1186 }
1187 if (cfg->refcount && (cfg->egress_dev == dev)) {
1188 /* Make sure the device is down before clearing any of
1189 * the mappings. Otherwise we could see a potential
1190 * race condition if packets are actively being
1191 * transmitted.
1192 */
1193 dev_close(vndev);
1194 rmnet_unset_logical_endpoint_config
1195 (vndev, RMNET_LOCAL_LOGICAL_ENDPOINT);
1196 vnd_work->vnd_id[j] = i;
1197 j++;
1198 }
1199 }
1200 if (j > 0) {
1201 vnd_work->count = j;
1202 schedule_work(&vnd_work->work);
1203 } else {
1204 kfree(vnd_work);
1205 }
1206
1207 /* Clear the mappings on the phys ep */
1208 trace_rmnet_unregister_cb_clear_lepcs(dev);
1209 rmnet_unset_logical_endpoint_config(dev, RMNET_LOCAL_LOGICAL_ENDPOINT);
1210 for (i = 0; i < RMNET_DATA_MAX_LOGICAL_EP; i++)
1211 rmnet_unset_logical_endpoint_config(dev, i);
1212 rmnet_unassociate_network_device(dev);
1213}
1214
1215/* rmnet_config_notify_cb() - Callback for netdevice notifier chain
1216 * @nb: Notifier block data
1217 * @event: Netdevice notifier event ID
1218 * @data: Contains a net device for which we are getting notified
1219 *
1220 * Return:
1221 * - result of NOTIFY_DONE()
1222 */
1223int rmnet_config_notify_cb(struct notifier_block *nb,
1224 unsigned long event, void *data)
1225{
1226 struct net_device *dev = netdev_notifier_info_to_dev(data);
1227
1228 if (!dev)
1229 return NOTIFY_DONE;
1230
1231 LOGL("(..., %lu, %s)", event, dev->name);
1232
1233 switch (event) {
1234 case NETDEV_UNREGISTER_FINAL:
1235 case NETDEV_UNREGISTER:
1236 trace_rmnet_unregister_cb_entry(dev);
1237 LOGH("Kernel is trying to unregister %s", dev->name);
1238 rmnet_force_unassociate_device(dev);
1239 trace_rmnet_unregister_cb_exit(dev);
1240 break;
1241
1242 default:
1243 trace_rmnet_unregister_cb_unhandled(dev);
1244 LOGD("Unhandeled event [%lu]", event);
1245 break;
1246 }
1247
1248 return NOTIFY_DONE;
1249}