Update to new sinfo resource variants API
[muen/linux/muennet.git] / net.c
1 /*
2  * Muen virtual network driver.
3  *
4  * Copyright (C) 2015  secunet Security Networks AG
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #define DRV_NAME        "muennet"
21 #define DRV_VERSION     "0.2"
22 #define DRV_DESCRIPTION "Muen SK virtual network driver"
23
24 #include <linux/module.h>
25 #include <linux/if_arp.h>
26 #include <linux/etherdevice.h>
27
28 #include "internal.h"
29
30 /**
31  * @file net.c
32  * @brief Networking interface
33  *
34  * @defgroup net Networking interface
35  *
36  * This module defines the module initialization and finalization code together
37  * with the whole implementation of network operations.
38  *
39  * The data is transferred via the #muennet_xmit function and received by the
40  * #muennet_reader_work work queue function.
41  */
42 /*@{*/
43
44 /**
45  * @brief List of networking drivers.
46  *
47  * This list is used to chain all initialized network interfaces together. The
48  * list head points to the #dev_info::list element of the network interfaces
49  * private data.
50  */
51 static LIST_HEAD(dev_list);
52
53 /**
54  * @brief Setup networking interface link.
55  *
56  * This function starts the network queue for the given interface and inserts
57  * the reader work into the events work queue.
58  *
59  * @param dev networking device to operate on
60  * @return always 0 to indicate success
61  */
62 static int muennet_open(struct net_device *dev)
63 {
64         struct dev_info *dev_info = netdev_priv(dev);
65
66         writer_up(dev_info);
67         netif_start_queue(dev);
68
69         schedule_delayed_work(&dev_info->reader_work, 0);
70
71         return 0;
72 }
73
74 /**
75  * @brief Teardown networking interface link.
76  *
77  * This function stops the network queue for this driver.
78  *
79  * @param dev the networking interface
80  * @return always returns 0
81  */
82 static int muennet_close(struct net_device *dev)
83 {
84         struct dev_info *dev_info = netdev_priv(dev);
85
86         netif_stop_queue(dev);
87         writer_down(dev_info);
88
89         return 0;
90 }
91
92 /**
93  * @brief Retrieve statistics about the networking interface.
94  *
95  * These statistics are shown in ifconfig or with "ip -s link". The following
96  * values are used:
97  * - rx_errors      : receive errors
98  * - rx_over_errors : reader was overrun by writer
99  * - rx_frame_error : invalid packet received from writer
100  * - rx_packets     : packets successfully received
101  * - rx_bytes       : sum of packet sizes successfully received
102  * - tx_dropped     : packet dropped because no writing memory region associated
103  * - tx_packets     : packets sent
104  * - tx_bytes       : sum of packet sizes successfully received
105  *
106  * @param dev network device
107  * @return reference to net_device_stats structure stored within private
108  * information #dev_info.
109  */
110 static struct net_device_stats *muennet_stats(struct net_device *dev)
111 {
112         struct dev_info *dev_info = netdev_priv(dev);
113
114         return &dev_info->stats;
115 }
116
117 /**
118  * @brief Retrieve ethtool settings.
119  *
120  * This function provides some dummy content to make ethtool happy.
121  *
122  * @param dev network interface
123  * @param cmd structure to be filled
124  * @return always returns 0
125  */
126 static int muennet_get_settings(struct net_device *dev,
127                                 struct ethtool_cmd *cmd)
128 {
129         cmd->supported = 0;
130         cmd->advertising = 0;
131         cmd->speed = SPEED_10;
132         cmd->duplex = DUPLEX_FULL;
133         cmd->port = PORT_TP;
134         cmd->phy_address = 0;
135         cmd->transceiver = XCVR_INTERNAL;
136         cmd->autoneg = AUTONEG_DISABLE;
137         cmd->maxtxpkt = 0;
138         cmd->maxrxpkt = 0;
139         return 0;
140 }
141
142 /**
143  * @brief Interface around strlcpy.
144  *
145  * This function is used to safely copy data into an array.
146  *
147  * @param array the (real) array to operate on
148  * @param value the string data to copy into the array
149  */
150 #define copy(array, value) strlcpy(array, value, sizeof(array))
151
152 /**
153  * @brief Retrieve driver information.
154  *
155  * This function is called to retrieve the information shown by "ethtool -i".
156  *
157  * @param dev  network interface
158  * @param info the structure to fill with the information
159  */
160 static void muennet_get_drvinfo(struct net_device *dev,
161                                 struct ethtool_drvinfo *info)
162 {
163         struct dev_info *dev_info = netdev_priv(dev);
164
165         copy(info->driver, DRV_NAME);
166         copy(info->version, DRV_VERSION);
167         copy(info->fw_version, "N/A");
168         copy(info->bus_info, dev_info->bus_info);
169 }
170
171 /**
172  * @brief Retrieve link information.
173  *
174  * This function tells the caller if the network interface has a link. A link
175  * is there if either a reader or a writer memory region is associated with
176  * this networking interface.
177  *
178  * @param dev network interface
179  * @return true if link is there
180  */
181 static u32 muennet_get_link(struct net_device *dev)
182 {
183         struct dev_info *dev_info = netdev_priv(dev);
184
185         return (dev_info->writer_element_size != 0 ||
186                 dev_info->reader_element_size != 0);
187 }
188
189 static void muennet_mclist(struct net_device *dev)
190 {
191         /*
192          * This callback is supposed to deal with mc filter in
193          * _rx_ path and has nothing to do with the _tx_ path.
194          * In rx path we always accept everything userspace gives us.
195          */
196 }
197
198 /**
199  * @brief ethtool operations
200  *
201  * This structure defines the ethtool operations available on this networking
202  * interface.
203  */
204 static const struct ethtool_ops muennet_ethtool_ops = {
205         .get_settings = muennet_get_settings,
206         .get_drvinfo  = muennet_get_drvinfo,
207         .get_link     = muennet_get_link,
208 };
209
210 /**
211  * @brief Networking interface destructor.
212  *
213  * This function is used to shutdown the reader and writer part and to free the
214  * allocated memory. It is called during unregister_netdev.
215  *
216  * @param dev the network interface
217  */
218
219 static void muennet_free(struct net_device *dev)
220 {
221         struct dev_info *dev_info = netdev_priv(dev);
222
223         cleanup_reader(dev_info);
224         cleanup_writer(dev_info);
225         kfree(dev_info->bus_info);
226 }
227
228 static const struct net_device_ops muennet_device_ops = {
229         .ndo_open       = muennet_open,
230         .ndo_stop       = muennet_close,
231         .ndo_start_xmit = muennet_xmit,
232         .ndo_get_stats  = muennet_stats,
233 };
234
235 static const struct net_device_ops muennet_dev_eth_ops = {
236         .ndo_open       = muennet_open,
237         .ndo_stop       = muennet_close,
238         .ndo_start_xmit = muennet_xmit,
239         .ndo_get_stats  = muennet_stats,
240         .ndo_set_rx_mode    = muennet_mclist,
241         .ndo_set_mac_address = eth_mac_addr,
242         .ndo_validate_addr = eth_validate_addr,
243         .ndo_features_check = passthru_features_check,
244 };
245
246 /**
247  * @brief Setup the network interface.
248  *
249  * This function is called during alloc_netdev to initialize the network
250  * operations for this interface.
251  *
252  * @param dev the network interface
253  */
254 static void muennet_setup(struct net_device *dev)
255 {
256         const struct dev_info *dev_info = netdev_priv(dev);
257
258         if (dev_info->flags & ETH_DEV)
259                 dev->netdev_ops = &muennet_dev_eth_ops;
260         else
261                 dev->netdev_ops = &muennet_device_ops;
262
263         dev->ethtool_ops = &muennet_ethtool_ops;
264         dev->needs_free_netdev = true;
265         dev->priv_destructor = muennet_free;
266 }
267
268 /**
269  * @brief Add a new networking interface.
270  *
271  * This function creates a new networking interface in the kernel based on the
272  * provided information.
273  *
274  * @param device_name name of the networking interface (%d is supported)
275  * @param input       name of the memory region to read from (use NULL or empty
276  *                    string to indicate no reading)
277  * @param output      name of the memory region to write from (use NULL or
278  *                    empty string to indicate no writing)
279  * @param mtu         the maximum transmission unit of this interface
280  * @param flags       flags that control the operation of the networking
281  *                    interface (see #muennet_flags for possible values)
282  * @param poll        poll interval to use for this network interface
283  *
284  * @return 0 on success
285  * @return -ENOMEM on memory allocation failure
286  * @return errors returned by #initialize_reader or #initialize_writer
287  */
288 static int add_device(const char *device_name,
289                       const char *input,
290                       const char *output,
291                       int mtu,
292                       const char *pmtu,
293                       u64 writer_protocol,
294                       u64 reader_protocol,
295                       unsigned long flags,
296                       unsigned int poll)
297 {
298         int ret = -ENOMEM;
299         struct net_device *dev;
300         struct dev_info *dev_info;
301         size_t bus_info_len = 2; /* place for separator and finishing \0 */
302
303         if (input)
304                 bus_info_len += strlen(input);
305         if (output)
306                 bus_info_len += strlen(output);
307
308         dev = alloc_netdev(sizeof(struct dev_info), device_name,
309                         NET_NAME_UNKNOWN, muennet_setup);
310         if (!dev)
311                 goto err;
312
313         /* do further initialization of device */
314
315         if (flags & ETH_DEV) {
316                 ether_setup(dev);
317                 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
318                 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
319                 eth_hw_addr_random(dev);
320
321                 /* Additional information is appended to skb */
322                 dev->needed_tailroom = sizeof(struct eth_hdr);
323         } else {
324                 dev->type = ARPHRD_NONE;
325                 dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
326                 dev->addr_len = 0;
327                 dev->hard_header_len = 0;
328                 dev->mtu = mtu;
329         }
330
331         if (flags & MUENNET_HDR)
332                 dev->hard_header_len += sizeof(struct net_hdr);
333
334         dev_info = netdev_priv(dev);
335         dev_info->dev = dev;
336
337         dev_info->bus_info = kmalloc(bus_info_len, GFP_KERNEL);
338         if (!dev_info->bus_info)
339                 goto err_free_netdev;
340         dev_info->bus_info[0] = 0;
341
342         if (input)
343                 strlcat(dev_info->bus_info, input, bus_info_len);
344         strlcat(dev_info->bus_info, ":", bus_info_len);
345         if (output)
346                 strlcat(dev_info->bus_info, output, bus_info_len);
347
348         dev_info->poll_interval = poll;
349         dev_info->mtu = mtu;
350         dev_info->flags = flags;
351         dev_info->writer_protocol = writer_protocol;
352         dev_info->reader_protocol = reader_protocol;
353
354         /* first check all the names */
355         if (input && strlen(input) > 0) {
356                 const struct muen_resource_type *const
357                         reader_channel = muen_get_resource(input,
358                                                            MUEN_RES_MEMORY);
359                 if (!reader_channel) {
360                         netdev_err(dev_info->dev,
361                                    "Input channel '%s' not found\n", input);
362                         goto err_free_businfo;
363                 }
364                 ret = initialize_reader(dev_info, reader_channel);
365                 if (ret < 0) {
366                         netdev_err(dev_info->dev,
367                                    "Unable to init reader (status: %d)\n", ret);
368                         goto err_free_businfo;
369                 }
370         }
371
372         if (output && strlen(output) > 0) {
373                 const struct muen_resource_type *const
374                         writer_channel = muen_get_resource(output,
375                                                            MUEN_RES_MEMORY);
376                 if (!writer_channel) {
377                         netdev_err(dev_info->dev,
378                                    "Output channel '%s' not found\n", output);
379                         goto err_cleanup_reader;
380                 }
381
382                 if (pmtu && strlen(pmtu) > 0) {
383                         const struct muen_resource_type *const
384                                 pmtu_channel = muen_get_resource(
385                                                 pmtu, MUEN_RES_MEMORY);
386                         if (!pmtu_channel) {
387                                 netdev_err(dev_info->dev,
388                                            "PMTU channel '%s' not found\n",
389                                            pmtu);
390                                 goto err_cleanup_reader;
391                         }
392                         ret = initialize_writer(dev_info, writer_channel,
393                                                 pmtu_channel);
394                 } else
395                         ret = initialize_writer(dev_info, writer_channel,
396                                                 NULL);
397
398                 if (ret < 0) {
399                         netdev_err(dev_info->dev,
400                                    "Unable to init writer (status: %d)\n", ret);
401                         goto err_cleanup_reader;
402                 }
403         }
404
405         ret = register_netdev(dev_info->dev);
406         if (ret < 0) {
407                 netdev_err(dev_info->dev,
408                            "register_netdev failed with status %d\n", ret);
409                 goto err_cleanup_writer;
410         }
411
412         list_add_tail(&dev_info->list, &dev_list);
413         debug_create_device(dev_info);
414         netdev_info(dev_info->dev, "Interface added\n");
415
416         return 0;
417
418 err_cleanup_writer:
419         cleanup_writer(dev_info);
420 err_cleanup_reader:
421         cleanup_reader(dev_info);
422 err_free_businfo:
423         kfree(dev_info->bus_info);
424 err_free_netdev:
425         free_netdev(dev);
426 err:
427         return ret;
428 }
429
430 /**
431  * @brief Maximum number of interfaces
432  *
433  * This is the maximum number of interfaces supported by the module parameters.
434  */
435 #define MAX_INTERFACES 32
436
437 /**
438  * @brief Poll interval (in µs)
439  *
440  * This is the default poll interval, use "poll" module parameter to override.
441  */
442 static unsigned int poll = 1;
443
444 /**
445  * @brief Interface names
446  *
447  * This array is filled with the list of interfaces specified with the "name"
448  * module parameter.
449  */
450 static char *name[MAX_INTERFACES];
451
452 /**
453  * @brief Input memory regions
454  *
455  * This array is filled with the list of input memory regions specified with
456  * the "in" module parameter.
457  */
458 static char *in[MAX_INTERFACES];
459
460 /**
461  * @brief Output memory regions
462  *
463  * This array is filled with the list of output memory regions specified with
464  * the "out" module parameter.
465  */
466 static char *out[MAX_INTERFACES];
467
468 /**
469  * @brief Maximum transfer unit
470  *
471  * This array is filled with the list of mtu specified with the "mtu" module
472  * parameter. If no MTU is given via module parameter a default value of 1500
473  * is used.
474  */
475 static char *mtu[MAX_INTERFACES];
476
477 /**
478  * @brief Memory regions for PMTU values
479  *
480  * This array is filled with the list of memory regions holding the PMTU values
481  * for each writer.
482  */
483 static char *pmtu[MAX_INTERFACES];
484
485 /**
486  * @brief Interface flags
487  *
488  * This array is filled with the list of interface flags specified with the
489  * "flags" module parameter. The flags are a list of names (see #flag_names for
490  * valid names) where the values for each interface are separated with "+" and
491  * the value list for all interfaces are separated with ",". If no flags are
492  * given for a interface a default value of 0 is used.
493  */
494 static char *flags[MAX_INTERFACES];
495
496 /**
497   * @brief Writer protocol
498   *
499   * This array is filled with the list of writer protocols specified with the
500   * writer_protocol parameter
501   */
502 static char *writer_protocol[MAX_INTERFACES];
503
504 /**
505   * @brief Reader protocol
506   *
507   * This array is filled with the list of reader protocols specified with the
508   * reader_protocol parameter
509   */
510 static char *reader_protocol[MAX_INTERFACES];
511
512 /**
513  * @brief Count of interface names
514  *
515  * This should be set to the number of interface names specified in the module
516  * parameters.
517  */
518 static int name_count;
519
520 module_param_array(name, charp, &name_count, 0444);
521 MODULE_PARM_DESC(name, "List of interface names, separated with comma");
522 module_param_array(in, charp, NULL, 0444);
523 MODULE_PARM_DESC(in, "List of input memregions, separated with comma (empty values permitted)");
524 module_param_array(out, charp, NULL, 0444);
525 MODULE_PARM_DESC(out, "List of output memregions, separated with comma (empty values permitted)");
526 module_param_array(pmtu, charp, NULL, 0444);
527 MODULE_PARM_DESC(pmtu, "List of input memregions holding PMTU values");
528 module_param_array(mtu, charp, NULL, 0444);
529 MODULE_PARM_DESC(mtu, "List of MTUs to use, separated with comma (default is 1500)");
530 module_param_array(writer_protocol, charp, NULL, 0444);
531 MODULE_PARM_DESC(writer_protocol, "List of writer protocol IDs, separated with comma");
532 module_param_array(reader_protocol, charp, NULL, 0444);
533 MODULE_PARM_DESC(reader_protocol, "List of reader protocol IDs, separated with comma");
534 module_param_array(flags, charp, NULL, 0444);
535 MODULE_PARM_DESC(flags, "List of flags separated with comma (flags for a device separated with +)");
536 module_param(poll, uint, 0444);
537 MODULE_PARM_DESC(poll, "Wait period in reader thread (in µs)");
538
539 /**
540  * @brief Parse interface flags for one interface.
541  *
542  * This function parses the interface flag names which are separated with "+".
543  * Case is important when comparing flag names. Unknown flag names result in an
544  * error.
545  *
546  * @param names list of flag names separated with "+" *
547  * @return resulting bit value. *
548  * @return -EINVAL if a flag is unknown
549  */
550 static int parse_flags(const char *names)
551 {
552         int result = 0;
553         int last_value = 0;
554         const char *next_pos;
555
556         while (!last_value) {
557                 size_t i;
558                 int found = 0;
559
560                 next_pos = strchr(names, '+');
561                 if (next_pos == NULL) {
562                         next_pos = names + strlen(names);
563                         last_value = 1;
564                 }
565
566                 for (i = 0; flag_names[i].name != NULL; i++) {
567                         if (strncmp(flag_names[i].name, names,
568                                     next_pos - names) == 0) {
569                                 result |= flag_names[i].value;
570                                 found = 1;
571                         }
572                 }
573
574                 if (!found) {
575                         pr_err(DRV_NAME ": Invalid flag name found in '%s'\n",
576                                names);
577                         return -EINVAL;
578                 }
579
580                 names = next_pos + 1;
581         }
582         return result;
583 }
584
585 /**
586  * @brief Module cleanup routine.
587  *
588  * This function is called during module unloading. It removes all debugfs
589  * entries and networking interfaces.
590  */
591 static void muennet_cleanup(void)
592 {
593         struct dev_info *dev_info;
594         struct dev_info *next;
595
596         list_for_each_entry_safe(dev_info, next, &dev_list, list) {
597                 list_del(&dev_info->list);
598                 debug_remove_device(dev_info);
599                 unregister_netdev(dev_info->dev);
600         }
601         debug_shutdown();
602 }
603
604 /**
605  * @brief Module initialization routine.
606  *
607  * This function parses the module parameters. For each interface specified by
608  * the "name" parameter a networking interface is created (with the memory
609  * region given by "in" and "out" parameters). If the setup of a network
610  * interface failed, all previously created network interfaces will be cleaned
611  * up and the error is returned to user space.
612  *
613  * @return 0 for successful module loading
614  * @return errors returned by #add_device
615  */
616
617 static int __init muennet_init(void)
618 {
619         int i;
620         int ret;
621
622         debug_initialize();
623
624         for (i = 0; i < name_count; i++) {
625                 unsigned int device_mtu = 1500;
626                 unsigned long flag_value = 0;
627                 u64 device_writer_protocol = 0;
628                 u64 device_reader_protocol = 0;
629
630                 if (!name[i] || strlen(name[i]) == 0)
631                         continue;
632
633                 if (mtu[i] != NULL && strlen(mtu[i]) > 0)
634                         if (kstrtouint(mtu[i], 10, &device_mtu) != 0) {
635                                 pr_err(DRV_NAME ": MTU invalid\n");
636                                 ret = -EINVAL;
637                                 goto error;
638                         };
639
640                 if (writer_protocol[i] != NULL &&
641                                 strlen(writer_protocol[i]) > 0)
642                         if (kstrtoull(writer_protocol[i], 16,
643                                       &device_writer_protocol) != 0) {
644                                 pr_err(DRV_NAME ": writer_protocol invalid\n");
645                                 ret = -EINVAL;
646                                 goto error;
647                         }
648
649                 if (reader_protocol[i] != NULL &&
650                                 strlen(reader_protocol[i]) > 0)
651                         if (kstrtoull(reader_protocol[i], 16,
652                                       &device_reader_protocol) != 0) {
653                                 pr_err(DRV_NAME ": reader_protocol invalid\n");
654                                 ret = -EINVAL;
655                                 goto error;
656                         }
657
658                 if (!device_reader_protocol) {
659                         pr_err(DRV_NAME ": reader_protocol missing\n");
660                         ret = -EINVAL;
661                         goto error;
662                 }
663
664                 if (flags[i] != NULL && strlen(flags[i]) > 0) {
665                         ret = parse_flags(flags[i]);
666                         if (ret < 0)
667                                 goto error;
668
669                         flag_value = ret;
670                 }
671
672                 ret = add_device(name[i], in[i], out[i], device_mtu, pmtu[i],
673                                  device_writer_protocol, device_reader_protocol,
674                                  flag_value, poll);
675                 if (ret < 0)
676                         goto error;
677         }
678         return 0;
679 error:
680         /* try to cleanup already created interfaces */
681         muennet_cleanup();
682         return ret;
683 }
684
685 module_init(muennet_init);
686 module_exit(muennet_cleanup);
687
688 MODULE_DESCRIPTION(DRV_DESCRIPTION);
689 MODULE_LICENSE("GPL");
690 MODULE_AUTHOR("Torsten Hilbrich <torsten.hilbrich@secunet.com>");
691
692 /*@}*/