diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/802.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/802.rst" new file mode 100644 index 0000000000000000000000000000000000000000..bac330c31dda08332eba3e3d85b8abd46775081e --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/802.rst" @@ -0,0 +1,212 @@ +802 Code Explanation +==================== + +This document provides a detailed breakdown of the functionalities in the 802 folder source code snippets, covering various aspects of Fibre Channel, FDDI, GARP, HIPPI, LLC Type 2, Ethernet II/IEEE 802.3, PSNAP, and STP. Additionally, it explains the open capabilities these modules provide to developers. + +fc.c (Fibre Channel) +-------------------- + +**Function Description** + +The ``fc.c`` file implements the data link layer handling for Fibre Channel, including frame header construction and device initialization. + +.. code-block:: c + + static int fc_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, + const void *daddr, const void *saddr, unsigned int len) + { + // ... + } + + static void fc_setup(struct net_device *dev) + { + // ... + } + +**Open Capabilities** + +- **Custom Header Creation**: Developers can extend the ``fc_header`` function to add custom header information. +- **Device Configuration**: Through the ``fc_setup`` function, developers can customize the initial configuration of the device, such as MTU and address length. + +fddi.c (Fiber Distributed Data Interface) +----------------------------------------- + +**Function Description** + +The ``fddi.c`` file contains the processing logic for FDDI network interfaces, including frame header creation and type conversion. + +.. code-block:: c + + static int fddi_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, + const void *daddr, const void *saddr, unsigned int len) + { + // ... + } + + __be16 fddi_type_trans(struct sk_buff *skb, struct net_device *dev) + { + // ... + } + +**Open Capabilities** + +- **Header Handling**: Developers can override the ``fddi_header`` function to customize the generation of FDDI headers. +- **Type Conversion**: The ``fddi_type_trans`` function allows developers to adjust the parsing logic for packet types according to specific needs. + +garp.c (Generic Attribute Registration Protocol) +------------------------------------------------ + +**Function Description** + +The ``garp.c`` file implements the Generic Attribute Registration Protocol (GARP), which allows network devices to dynamically exchange information about supported attributes. + +.. code-block:: c + + static const u8 + mrp_applicant_state_table[MRP_APPLICANT_MAX + 1][MRP_EVENT_MAX + 1] = { + // ... state table definition ... + }; + +**Open Capabilities** + +- **State Management**: Developers can modify the ``mrp_applicant_state_table`` to customize the state transition logic for GARP applicants. +- **Event Handling**: By implementing custom event handling functions, developers can extend the behavior of GARP. + +hippi.c (High-Performance Parallel Interface) +--------------------------------------------- + +**Function Description** + +The ``hippi.c`` file provides support for the High-Performance Parallel Interface (HIPPI), an early high-speed data transfer standard. + +.. code-block:: c + + struct net_device *alloc_hippi_dev(int sizeof_priv) + { + // ... + } + +**Open Capabilities** + +- **Device Initialization**: Developers can use the ``alloc_hippi_dev`` function to create and initialize new HIPPI devices. +- **Custom Setup**: Through the ``hippi_setup`` function, developers can customize the initial configuration of HIPPI devices. + +mrp.c (Multiple Registration Protocol) +-------------------------------------- + +**Function Description** + +The ``mrp.c`` file implements the Multiple Registration Protocol (MRP), which provides redundant paths in the network to ensure reliability. + +.. code-block:: c + + void mrp_unregister_application(struct mrp_application *appl) + { + // ... + } + +**Open Capabilities** + +- **Application Registration and Unregistration**: Developers can register and unregister MRP applications using the ``mrp_register_application`` and ``mrp_unregister_application`` functions. +- **Message Handling**: By implementing custom message handling functions, developers can extend the behavior of MRP. + +p8022.c (LLC Type 2) +-------------------- + +**Function Description** + +The ``p8022.c`` file implements the Logical Link Control (LLC) Type 2, which is part of the data link layer and is responsible for error detection and flow control. + +.. code-block:: c + + struct datalink_proto *register_8022_client(unsigned char type, + int (*func)(struct sk_buff *skb, + struct net_device *dev, + struct packet_type *pt, + struct net_device *orig_dev)) + { + // ... + } + + static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb, + unsigned char *dest) + { + // ... + } + +**Open Capabilities** + +- **Client Registration**: Developers can register their own 802.2 clients using the ``register_8022_client`` function. +- **Frame Handling**: By implementing custom frame handling functions, developers can extend the behavior of 802.2. + +p8023.c (Ethernet II and IEEE 802.3) +------------------------------------ + +**Function Description** + +The ``p8023.c`` file provides support for the Ethernet II and IEEE 802.3 protocols, which are the most common LAN technologies. + +.. code-block:: c + + struct datalink_proto *make_8023_client(void) + { + // ... + } + + static int p8023_request(struct datalink_proto *dl, + struct sk_buff *skb, unsigned char *dest_node) + { + // ... + } + +**Open Capabilities** + +- **Client Creation**: Developers can create 802.3 clients using the ``make_8023_client`` function. +- **Frame Handling**: By implementing custom frame handling functions, developers can extend the behavior of 802.3. + +psnap.c (Protocol Simple Network Access Protocol) +------------------------------------------------- + +**Function Description** + +The ``psnap.c`` file implements the Protocol Simple Network Access Protocol (PSNAP), which allows the encapsulation and transmission of multiple protocols through SNAP. + +.. code-block:: c + + static struct datalink_proto *find_snap_client(const unsigned char *desc) + { + // ... + } + + static int snap_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) + { + // ... + } + +**Open Capabilities** + +- **Client Registration**: Developers can register their own SNAP clients using the ``register_snap_client`` function. +- **Frame Handling**: By implementing custom frame handling functions, developers can extend the behavior of SNAP. + +stp.c (Spanning Tree Protocol) +------------------------------ + +**Function Description** + +The ``stp.c`` file implements the Spanning Tree Protocol (STP), which prevents loops in Layer 2 networks by blocking certain ports. + +.. code-block:: c + + static int stp_pdu_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev) + { + // ... + } + +**Open Capabilities** + +- **Protocol Handling**: Developers can implement custom protocol handlers to extend the behavior of STP. +- **Message Handling**: By implementing custom message handling functions, developers can extend the event handling logic of STP. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/8021q.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/8021q.rst" new file mode 100644 index 0000000000000000000000000000000000000000..25610e8af59297053402062b9dc278c5619f7040 --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/8021q.rst" @@ -0,0 +1,210 @@ +.. 8021q VLAN Code Explanation +.. ======================= + +Kconfig +------- +The `Kconfig` file defines the configuration options for the 802.1Q VLAN support. It allows users to enable or disable 802.1Q VLAN, GVRP, and MVRP through the kernel configuration menu. + +.. code-block:: c + + config VLAN_8021Q + tristate "802.1Q/802.1ad VLAN Support" + help + Select this and you will be able to create 802.1Q VLAN interfaces + on your Ethernet interfaces. 802.1Q VLAN supports almost + everything a regular Ethernet interface does, including + firewalling, bridging, and of course IP traffic. + To compile this code as a module, choose M here: the module + will be called 8021q. + If unsure, say N. + + config VLAN_8021Q_GVRP + bool "GVRP (GARP VLAN Registration Protocol) support" + depends on VLAN_8021Q + select GARP + help + Select this to enable GVRP end-system support. GVRP is used for + automatic propagation of registered VLANs to switches. + If unsure, say N. + + config VLAN_8021Q_MVRP + bool "MVRP (Multiple VLAN Registration Protocol) support" + depends on VLAN_8021Q + select MRP + help + Select this to enable MVRP end-system support. MVRP is used for + automatic propagation of registered VLANs to switches; it + supersedes GVRP and is not backwards-compatible. + If unsure, say N. + +Makefile +-------- +The `Makefile` specifies which object files are to be built based on the configuration. It ensures that the necessary components for 802.1Q, GVRP, and MVRP are compiled when the corresponding features are enabled. + +.. code-block:: make + + obj-$(subst m,y,$(CONFIG_VLAN_8021Q)) += vlan_core.o + obj-$(CONFIG_VLAN_8021Q) += 8021q.o + 8021q-y := vlan.o vlan_dev.o vlan_netlink.o + 8021q-$(CONFIG_VLAN_8021Q_GVRP) += vlan_gvrp.o + 8021q-$(CONFIG_VLAN_8021Q_MVRP) += vlan_mvrp.o + 8021q-$(CONFIG_PROC_FS) += vlanproc.o + +vlan.c +------ +The `vlan.c` file is the main entry point for the 802.1Q VLAN subsystem. It includes initialization and cleanup routines as well as general operations. + +.. code-block:: c + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include + #include + #include + #include + #include + #include + #include + + static int __init vlan_proto_init(void) + { + int err; + err = register_pernet_subsys(&vlan_net_ops); + if (err < 0) + goto err0; + err = register_netdevice_notifier(&vlan_notifier_block); + if (err < 0) + goto err2; + err = vlan_gvrp_init(); + if (err < 0) + goto err3; + err = vlan_mvrp_init(); + if (err < 0) + goto err4; + err = vlan_netlink_init(); + if (err < 0) + goto err5; + vlan_ioctl_set(vlan_ioctl_handler); + return 0; + err5: + vlan_mvrp_uninit(); + err4: + vlan_gvrp_uninit(); + err3: + unregister_netdevice_notifier(&vlan_notifier_block); + err2: + unregister_pernet_subsys(&vlan_net_ops); + err0: + return err; + } + module_init(vlan_proto_init); + + static void __exit vlan_cleanup_module(void) + { + vlan_ioctl_set(NULL); + vlan_netlink_fini(); + unregister_netdevice_notifier(&vlan_notifier_block); + unregister_pernet_subsys(&vlan_net_ops); + rcu_barrier(); /* Wait for completion of call_rcu()'s */ + vlan_mvrp_uninit(); + vlan_gvrp_uninit(); + } + module_exit(vlan_cleanup_module); + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + + +vlan_gvrp.c +----------- +The `vlan_gvrp.c` file contains the implementation of the GVRP protocol, which is used for automatic propagation of registered VLANs to switches. + +.. code-block:: c + + int vlan_gvrp_request_join(const struct net_device *dev) + { + const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + __be16 vlan_id = htons(vlan->vlan_id); + if (vlan->vlan_proto != htons(ETH_P_8021Q)) + return 0; + return garp_request_join(vlan->real_dev, &vlan_gvrp_app, + &vlan_id, sizeof(vlan_id), GVRP_ATTR_VID); + } + + void vlan_gvrp_request_leave(const struct net_device *dev) + { + const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + __be16 vlan_id = htons(vlan->vlan_id); + if (vlan->vlan_proto != htons(ETH_P_8021Q)) + return; + garp_request_leave(vlan->real_dev, &vlan_gvrp_app, + &vlan_id, sizeof(vlan_id), GVRP_ATTR_VID); + } + +vlan_mvrp.c +----------- +The `vlan_mvrp.c` file contains the implementation of the MVRP protocol, which is an extension of GVRP and is not backwards-compatible. + +.. code-block:: c + + int vlan_mvrp_request_join(const struct net_device *dev) + { + const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + __be16 vlan_id = htons(vlan->vlan_id); + if (vlan->vlan_proto != htons(ETH_P_8021Q)) + return 0; + return mrp_request_join(vlan->real_dev, &vlan_mrp_app, + &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID); + } + + void vlan_mvrp_request_leave(const struct net_device *dev) + { + const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + __be16 vlan_id = htons(vlan->vlan_id); + if (vlan->vlan_proto != htons(ETH_P_8021Q)) + return; + mrp_request_leave(vlan->real_dev, &vlan_mrp_app, + &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID); + } + +vlan_netlink.c +-------------- +The `vlan_netlink.c` file provides a Netlink interface for configuring and querying VLAN settings from user space. + +.. code-block:: c + + static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = { + [IFLA_VLAN_ID] = { .type = NLA_U16 }, + [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) }, + [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED }, + [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED }, + [IFLA_VLAN_PROTOCOL] = { .type = NLA_U16 }, + }; + + static int vlan_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) + { + ... + return 0; + } + + static int vlan_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], struct netlink_ext_ack *extack) + { + ... + + return 0; + } + + +Open Capabilities for Developers +-------------------------------- +The 802.1Q VLAN subsystem provides several open capabilities to developers, allowing them to extend and customize the behavior of VLANs: + +1. **Custom VLAN Names**: Developers can modify the naming scheme for VLAN interfaces by changing the `name_type` in the `vlan_net` structure. This can be useful for integrating with specific network management systems. + +2. **VLAN Tag Handling**: The `vlan_gro_receive` and `vlan_gro_complete` functions provide hooks for handling incoming and outgoing VLAN-tagged packets. Developers can extend these functions to add custom logic, such as additional packet inspection or modification. + +3. **Netlink Interface**: The Netlink interface in `vlan_netlink.c` allows for dynamic configuration of VLANs. Developers can use this interface to create, delete, and manage VLANs programmatically from user space, enabling automation and integration with other network management tools. + +4. **GVRP and MVRP Customization**: The `vlan_gvrp.c` and `vlan_mvrp.c` files implement the GVRP and MVRP protocols, respectively. Developers can extend these protocols to support custom behaviors, such as enhanced security checks or logging. + +5. **Proc Filesystem Entries**: The `/proc` filesystem entries in `vlanproc.c` can be extended to provide more detailed information about VLANs, such as statistics, error counts, or other relevant data. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/9p.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/9p.rst" new file mode 100644 index 0000000000000000000000000000000000000000..2bfe52a9b2895dc7889950bc6705c338c9bd6e0c --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/9p.rst" @@ -0,0 +1,266 @@ +This document provides a detailed breakdown of the 9P file system kernel module source code, covering client option parsing, protocol support, error handling mechanisms, and various transport implementations. Additionally, it will cover the open capabilities provided by 9P for developers. + +.. Kconfig +.. -------------- +.. **Function Description** +.. The Kconfig file defines configuration options related to the 9P protocol, allowing users to enable or disable 9P support through the kernel configuration tools (e.g., `make menuconfig`). + +.. code-block:: c + + menuconfig NET_9P + depends on NET + tristate "Plan 9 Resource Sharing Support (9P2000)" + help + If you say Y here, you will get experimental support for + Plan 9 resource sharing via the 9P2000 protocol. + See for more information. + If unsure, say N. + + if NET_9P + config NET_9P_VIRTIO + depends on VIRTIO + tristate "9P Virtio Transport" + help + This builds support for a transport between guest partitions and a host partition. + + config NET_9P_XEN + depends on XEN + select XEN_XENBUS_FRONTEND + tristate "9P Xen Transport" + help + This builds support for a transport for 9pfs between two Xen domains. + + config NET_9P_RDMA + depends on INET && INFINIBAND && INFINIBAND_ADDR_TRANS + tristate "9P RDMA Transport (Experimental)" + help + This builds support for an RDMA transport. + + config NET_9P_DEBUG + bool "Debug information" + help + Say Y if you want the 9P subsystem to log debug information. + Endif + +.. Makefile +.. -------------- +.. **Function Description** +.. The Makefile defines the build targets and rules required to compile the 9P file system kernel module. + +.. code-block:: make + + obj-$(CONFIG_NET_9P) := 9pnet.o + obj-$(CONFIG_NET_9P_XEN) += 9pnet_xen.o + obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o + obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o + + 9pnet-objs := \ + mod.o \ + client.o \ + error.o \ + protocol.o \ + trans_fd.o \ + trans_common.o \ + + 9pnet_virtio-objs := trans_virtio.o + 9pnet_xen-objs := trans_xen.o + 9pnet_rdma-objs := trans_rdma.o + +.. mod.c +.. -------------- +.. **Function Description** +.. `mod.c` contains the initialization and exit functions for the 9P file system module, responsible for registering and unloading the 9P file system. + +.. code-block:: c + + static int __init init_p9(void) + { + int ret; + ret = p9_client_init(); + if (ret) + return ret; + p9_error_init(); + pr_info("Installing 9P2000 support\n"); + p9_trans_fd_init(); + return ret; + } + + static void __exit exit_p9(void) + { + pr_info("Unloading 9P2000 support\n"); + p9_trans_fd_exit(); + p9_client_exit(); + } + module_init(init_p9); + module_exit(exit_p9); + +.. client.c +.. -------------- +.. **Function Description** +.. `client.c` handles 9P client requests and responses, including parsing client options and displaying client configuration information. + +.. code-block:: c + + int p9_show_client_options(struct seq_file *m, struct p9_client *clnt) + { + if (clnt->msize != 8192) + seq_printf(m, ",msize=%u", clnt->msize); + seq_printf(m, ",trans=%s", clnt->trans_mod->name); + switch (clnt->proto_version) { + case p9_proto_legacy: + seq_puts(m, ",noextend"); + break; + case p9_proto_2000u: + seq_puts(m, ",version=9p2000.u"); + break; + case p9_proto_2000L: + /* Default */ + break; + } + if (clnt->trans_mod->show_options) + return clnt->trans_mod->show_options(m, clnt); + return 0; + } + EXPORT_SYMBOL(p9_show_client_options); + + struct p9_fid *p9_fid_create(struct p9_client *clnt) + { + int ret; + struct p9_fid *fid; + p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt); + fid = kzalloc(sizeof(struct p9_fid), GFP_KERNEL); + if (!fid) + return NULL; + fid->mode = -1; + fid->uid = current_fsuid(); + fid->clnt = clnt; + idr_preload(GFP_KERNEL); + spin_lock_irq(&clnt->lock); + ret = idr_alloc_u32(&clnt->fids, fid, &fid->fid, P9_NOFID - 1, GFP_NOWAIT); + spin_unlock_irq(&clnt->lock); + idr_preload_end(); + if (!ret) + return fid; + kfree(fid); + return NULL; + } + +.. error.c +.. -------------- +.. **Function Description** +.. `error.c` provides a mapping from Plan 9 string errors to Linux numeric error codes. + +.. code-block:: c + + int p9_error_init(void) + { + struct errormap *c; + int bucket; + for (bucket = 0; bucket < ERRHASHSZ; bucket++) + INIT_HLIST_HEAD(&hash_errmap[bucket]); + for (c = errmap; c->name != NULL; c++) { + c->namelen = strlen(c->name); + bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; + INIT_HLIST_NODE(&c->list); + hlist_add_head(&c->list, &hash_errmap[bucket]); + } + return 1; + } + EXPORT_SYMBOL(p9_error_init); + + int p9_errstr2errno(char *errstr, int len) + { + int errno; + struct errormap *c; + int bucket; + errno = 0; + c = NULL; + bucket = jhash(errstr, len, 0) % ERRHASHSZ; + hlist_for_each_entry(c, &hash_errmap[bucket], list) { + if (c->namelen == len && !memcmp(c->name, errstr, len)) { + errno = c->val; + break; + } + } + if (errno == 0) { + errstr[len] = 0; + pr_err("%s: server reported unknown error %s\n", __func__, errstr); + errno = ESERVERFAULT; + } + return -errno; + } + EXPORT_SYMBOL(p9_errstr2errno); + +.. protocol.c & protocol.h +.. -------------- +.. **Function Description** +.. `protocol.c` and `protocol.h` implement the message encoding/decoding logic for the 9P protocol, defining data structures and interfaces for protocol operations. + +.. code-block:: c + + size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) + { + size_t len = min(pdu->size - pdu->offset, size); + memcpy(data, &pdu->sdata[pdu->offset], len); + pdu->offset += len; + return size - len; + } + + void p9stat_free(struct p9_wstat *stbuf) + { + kfree(stbuf->name); + stbuf->name = NULL; + kfree(stbuf->uid); + stbuf->uid = NULL; + kfree(stbuf->gid); + stbuf->gid = NULL; + kfree(stbuf->muid); + stbuf->muid = NULL; + kfree(stbuf->extension); + stbuf->extension = NULL; + } + EXPORT_SYMBOL(p9stat_free); + +.. trans_common.c & trans_common.h +.. -------------- +.. **Function Description** +.. `trans_common.c` and `trans_common.h` provide common functionality used by all transport methods, such as page release. + +.. code-block:: c + + void p9_release_pages(struct page **pages, int nr_pages) + { + int i; + for (i = 0; i < nr_pages; i++) + if (pages[i]) + put_page(pages[i]); + } + EXPORT_SYMBOL(p9_release_pages); + + +.. Open Capabilities Provided by 9P for Developers +.. ---------------------------------------------- +9P file system kernel module offers the following open capabilities for developers: + +1. **Multi-Version Support**: + - 9P supports multiple versions of the protocol, including 9P2000.L, 9P2000.u, and 9P2000. Developers can choose the appropriate version based on their needs. + +2. **Multiple Transport Methods**: + - 9P supports various transport methods, including TCP, RDMA, VirtIO, and Xen. Developers can select the most suitable transport method for their application scenarios. + +3. **Flexible Configuration Options**: + - Through Kconfig, developers can flexibly configure 9P support options, such as enabling debug information and setting the default transport method. + +4. **Comprehensive Error Handling Mechanism**: + - 9P provides a complete error handling mechanism, converting Plan 9 error strings to standard Linux error codes, making it easier for developers to handle errors and log them. + +5. **Detailed Logging**: + - 9P supports detailed logging. Developers can enable debug information through configuration to help diagnose and resolve issues. + +6. **Extensibility**: + - 9P's design is modular, allowing developers to easily add new transport methods or other functionalities to meet specific requirements. + +7. **Exported APIs**: + - 9P exports several APIs, such as `p9_is_proto_dotl`, `p9_is_proto_dotu`, and `p9_show_client_options`. Developers can use these APIs in their modules to interact with 9P. + +Through these features and open capabilities, the 9P file system kernel module provides a powerful and flexible solution for distributed file systems. This document aims to help you better understand and utilize the 9P file system. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/dcb.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/dcb.rst" new file mode 100644 index 0000000000000000000000000000000000000000..41d2b0571a299c5021ea42be9c855d67fd916d53 --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/dcb.rst" @@ -0,0 +1,107 @@ +.. DCB +======= + +Overview +-------- + +The `dcb` module implements support for Data Center Bridging (DCB), which is a set of Ethernet enhancements that allow different types of network traffic with varying requirements (such as high reliability, no packet loss, and low latency) to coexist on the same Ethernet link. The main features of DCB include: + +- **Enhanced Transmission Selection (ETS)**: Provides a framework for assigning bandwidth guarantees to traffic classes. +- **Priority-based Flow Control (PFC)**: Offers flow control mechanisms that can work independently for each 802.1p priority. +- **Congestion Notification**: Provides end-to-end congestion control for protocols without built-in congestion management. + +Key Files +--------- + +- **dcbevent.c**: Manages event notifications related to DCB. +- **dcbnl.c**: Implements the rtnetlink interface for configuring DCB features. + +Function Descriptions +--------------------- + +### dcbevent.c + +**Function Description** +The `dcbevent.c` file contains functions for managing event notifications related to DCB, allowing other kernel components to be notified of changes or events. + +.. code-block:: c + + int register_dcbevent_notifier(struct notifier_block *nb) + { + return atomic_notifier_chain_register(&dcbevent_notif_chain, nb); + } + + int unregister_dcbevent_notifier(struct notifier_block *nb) + { + return atomic_notifier_chain_unregister(&dcbevent_notif_chain, nb); + } + + int call_dcbevent_notifiers(unsigned long val, void *v) + { + return atomic_notifier_call_chain(&dcbevent_notif_chain, val, v); + } + +**Open Capabilities** +- **Custom Notifier Registration**: Developers can create their own `notifier_block` structures and use `register_dcbevent_notifier` to receive notifications about DCB-related events. +- **Event Handling**: By implementing the `notifier_call` function within the `notifier_block`, developers can define custom behavior in response to DCB events. + +### dcbnl.c + +**Function Description** +The `dcbnl.c` file provides the rtnetlink interface for configuring DCB features, including setting and getting parameters for ETS, PFC, and application priorities. + +.. code-block:: c + + static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) + { + if (!netdev->dcbnl_ops->getstate) + return -EOPNOTSUPP; + return nla_put_u8(skb, DCB_ATTR_STATE, netdev->dcbnl_ops->getstate(netdev)); + } + + static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, + u32 seq, struct nlattr **tb, struct sk_buff *skb) + { + struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; + u8 value; + int ret; + int i; + int getall = 0; + + if (!tb[DCB_ATTR_PFC_CFG]) + return -EINVAL; + if (!netdev->dcbnl_ops->getpfccfg) + return -EOPNOTSUPP; + ret = nla_parse_nested_deprecated(data, DCB_PFC_UP_ATTR_MAX, + tb[DCB_ATTR_PFC_CFG], + dcbnl_pfc_up_nest, NULL); + if (ret) + return ret; + + nest = nla_nest_start_noflag(skb, DCB_ATTR_PFC_CFG); + if (!nest) + return -EMSGSIZE; + + if (data[DCB_PFC_UP_ATTR_ALL]) + getall = 1; + + for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { + if (!getall && !data[i]) + continue; + netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value); + ret = nla_put_u8(skb, i, value); + if (ret) + //Part of the source code is omitted here + } + +**Open Capabilities** +- **Configuration Access**: Developers can access and modify the DCB configuration of network devices through the provided rtnetlink operations. +- **Custom Feature Support**: By extending the `dcbnl_ops` structure, developers can add support for additional DCB features or customize existing ones. + +Open Capabilities +----------------- + +- **Notification System Extension**: Developers can extend the notification system by adding new notifiers to handle specific events. +- **rtnetlink Interface Customization**: Through the rtnetlink API, developers can implement custom logic to interact with the DCB settings of network interfaces, such as retrieving or updating configurations. +- **Device-Specific Enhancements**: By modifying or extending the `dcbnl_ops` structure, developers can tailor the DCB functionality to better fit the needs of specific network hardware. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/iucv.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/iucv.rst" new file mode 100644 index 0000000000000000000000000000000000000000..7b2b9af3a23b8d8c24f69f19d683a2a7606dd861 --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/iucv.rst" @@ -0,0 +1,209 @@ +IUCV +===== + +af_iucv.c (AF_IUCV Sockets) +--------------------------- + +**Function Description** +The `af_iucv.c` file implements the socket layer interface for the IUCV protocol stack, allowing user-space programs to use IUCV for communication. It includes key functions such as creating and destroying sockets, binding addresses, listening for connection requests, and handling data transmission. + +.. code-block:: c + :linenos: + + static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio, int kern) { + struct sock *sk; + struct iucv_sock *iucv; + sk = sk_alloc(&init_net, PF_IUCV, prio, &iucv_proto, kern); + if (!sk) + return NULL; + iucv = iucv_sk(sk); + sock_init_data(sock, sk); + INIT_LIST_HEAD(&iucv->accept_q); + spin_lock_init(&iucv->accept_q_lock); + skb_queue_head_init(&iucv->send_skb_q); + INIT_LIST_HEAD(&iucv->message_q.list); + spin_lock_init(&iucv->message_q.lock); + skb_queue_head_init(&iucv->backlog_skb_q); + iucv->send_tag = 0; + atomic_set(&iucv->pendings, 0); + iucv->flags = 0; + iucv->msglimit = 0; + atomic_set(&iucv->msg_sent, 0); + atomic_set(&iucv->msg_recv, 0); + iucv->path = NULL; + iucv->sk_txnotify = afiucv_hs_callback_txnotify; + memset(&iucv->src_user_id, 0, 32); + if (pr_iucv) + iucv->transport = AF_IUCV_TRANS_IUCV; + else + iucv->transport = AF_IUCV_TRANS_HIPER; + sk->sk_destruct = iucv_sock_destruct; + sk->sk_sndtimeo = IUCV_CONN_TIMEOUT; + sock_reset_flag(sk, SOCK_ZAPPED); + sk->sk_protocol = proto; + sk->sk_state = IUCV_OPEN; + iucv_sock_link(&iucv_sk_list, sk); + return sk; + } + + static void iucv_accept_enqueue(struct sock *parent, struct sock *sk) { + unsigned long flags; + struct iucv_sock *par = iucv_sk(parent); + sock_hold(sk); + spin_lock_irqsave(&par->accept_q_lock, flags); + list_add_tail(&iucv_sk(sk)->accept_q, &par->accept_q); + spin_unlock_irqrestore(&par->accept_q_lock, flags); + iucv_sk(sk)->parent = parent; + sk_acceptq_added(parent); + } + + static int iucv_callback_connreq(struct iucv_path *path, u8 ipvmid[8], u8 ipuser[16]) { + unsigned char user_data[16]; + unsigned char nuser_data[16]; + unsigned char src_name[8]; + struct sock *sk, *nsk; + struct iucv_sock *iucv, *niucv; + int err; + memcpy(src_name, ipuser, 8); + EBCASC(src_name, 8); + read_lock(&iucv_sk_list.lock); + iucv = NULL; + sk = NULL; + sk_for_each(sk, &iucv_sk_list.head) + if (sk->sk_state == IUCV_LISTEN && + !memcmp(&iucv_sk(sk)->src_name, src_name, 8)) { + iucv = iucv_sk(sk); + break; + } + read_unlock(&iucv_sk_list.lock); + if (!iucv) + return -EINVAL; + bh_lock_sock(sk); + low_nmcpy(user_data, iucv->src_name); + high_nmcpy(user_data, iucv->dst_name); + ASCEBC(user_data, sizeof(user_data)); + if (sk->sk_state != IUCV_LISTEN) { + err = pr_iucv->path_sever(path, user_data); + iucv_path_free(path); + goto fail; + } + if (sk_acceptq_is_full(sk)) { + err = pr_iucv->path_sever(path, user_data); + iucv_path_free(path); + goto fail; + } + nsk = iucv_sock_alloc(NULL, sk->sk_protocol, GFP_ATOMIC, 0); + if (!nsk) { + err = pr_iucv->path_sever(path, user_data); + iucv_path_free(path); + goto fail; + } + niucv = iucv_sk(nsk); + iucv_sock_init(nsk, sk); + niucv->transport = AF_IUCV_TRANS_IUCV; + nsk->sk_allocation |= GFP_DMA; + memcpy(niucv->dst_name, ipuser + 8, 8); + EBCASC(niucv->dst_name, 8); + memcpy(niucv->dst_user_id, ipvmid, 8); + memcpy(niucv->src_name, iucv->src_name, 8); + memcpy(niucv->src_user_id, iucv->src_user_id, 8); + niucv->path = path; + high_nmcpy(nuser_data, ipuser + 8); + memcpy(nuser_data + 8, niucv->src_name, 8); + ASCEBC(nuser_data + 8, 8); + niucv->msglimit = iucv->msglimit; + path->msglim = iucv->msglimit; + err = pr_iucv->path_accept(path, &af_iucv_handler, nuser_data, nsk); + if (err) { + iucv_sever_path(nsk, 1); + iucv_sock_kill(nsk); + goto fail; + } + iucv_accept_enqueue(sk, nsk); + nsk->sk_state = IUCV_CONNECTED; + sk->sk_data_ready(sk); + err = 0; + fail: + release_sock(sk); + return err; + } + +**Open Capabilities** +- **Custom Socket Behavior**: Developers can extend or modify the socket allocation and initialization logic to support specific application scenarios. +- **Connection Management**: By overriding or extending existing callback functions, such as `iucv_callback_connreq`, developers can control how new connection requests are handled, enabling more advanced security and policy controls. +- **Data Flow Control**: When sending and receiving data, developers can optimize performance by adjusting socket parameters, such as setting message limits (`msglimit`). + +iucv.c (IUCV Base Infrastructure) +--------------------------------- + +**Function Description** +The `iucv.c` file provides the base infrastructure support for IUCV, including path management, interrupt handling, and the execution of underlying IUCV commands. + +.. code-block:: c + :linenos: + + static void iucv_callback_rx(struct iucv_path *path, struct iucv_message *msg) { + struct sock *sk = path->private; + struct iucv_sock *iucv = iucv_sk(sk); + struct sk_buff *skb; + struct sock_msg_q *save_msg; + int len; + if (sk->sk_shutdown & RCV_SHUTDOWN) { + pr_iucv->message_reject(path, msg); + return; + } + spin_lock(&iucv->message_q.lock); + if (!list_empty(&iucv->message_q.list) || + !skb_queue_empty(&iucv->backlog_skb_q)) + goto save_message; + len = atomic_read(&sk->sk_rmem_alloc); + len += SKB_TRUESIZE(iucv_msg_length(msg)); + if (len > sk->sk_rcvbuf) + goto save_message; + skb = alloc_iucv_recv_skb(iucv_msg_length(msg)); + if (!skb) + goto save_message; + iucv_process_message(sk, skb, path, msg); + goto out_unlock; + save_message: + save_msg = kzalloc(sizeof(struct sock_msg_q), GFP_ATOMIC | GFP_DMA); + if (!save_msg) + goto out_unlock; + save_msg->path = path; + save_msg->msg = *msg; + list_add_tail(&save_msg->list, &iucv->message_q.list); + out_unlock: + spin_unlock(&iucv->message_q.lock); + } + + static void iucv_callback_txdone(struct iucv_path *path, struct iucv_message *msg) { + struct sock *sk = path->private; + struct sk_buff *this = NULL; + struct sk_buff_head *list = &iucv_sk(sk)->send_skb_q; + struct sk_buff *list_skb; + unsigned long flags; + bh_lock_sock(sk); + while ((list_skb = __skb_dequeue(list))) { + if (list_skb == this) { + kfree_skb(list_skb); + if (sk->sk_state == IUCV_CONNECTED) { + sk->sk_state = IUCV_DISCONN; + sk->sk_state_change(sk); + } + break; + } + break; + } + spin_unlock_irqrestore(&list->lock, flags); + if (sk->sk_state == IUCV_CLOSING) { + if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) { + sk->sk_state = IUCV_CLOSED; + sk->sk_state_change(sk); + } + } + } + +**Open Capabilities** +- **CPU Preparation and Cleanup**: Developers can customize the preparation and cleanup of CPUs during system startup or shutdown to accommodate special requirements. +- **Path Management**: By calling functions like `iucv_sever_path`, developers can manually manage IUCV paths, providing direct control over network topology. +- **Message Handling**: By implementing their own `iucv_callback_rx` and `iucv_callback_txdone` callbacks, developers can process received data packets and handle transmission completions according to application needs, enabling filtering, forwarding, or other business logic. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/l3mdev.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/l3mdev.rst" new file mode 100644 index 0000000000000000000000000000000000000000..827e96c6782b89460ae83f6c3c1e34b9817f7f8b --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/l3mdev.rst" @@ -0,0 +1,118 @@ +l3mdev +================ + +l3mdev.c (L3 Master Device) +--------------------------- +**Function Description** + +The `l3mdev.c` file implements the L3 master device support, which allows the core networking code to interact with device drivers that manage L3 master devices like VRF. The following are key functions and their descriptions: + +.. code-block:: c + int l3mdev_table_lookup_register(enum l3mdev_type l3type, lookup_by_table_id_t fn) + { + struct l3mdev_handler *hdlr; + int res; + + res = l3mdev_check_type(l3type); + if (res) + return res; + hdlr = &l3mdev_handlers[l3type]; + spin_lock(&l3mdev_lock); + if (hdlr->dev_lookup) { + res = -EBUSY; + goto unlock; + } + hdlr->dev_lookup = fn; + res = 0; + unlock: + spin_unlock(&l3mdev_lock); + return res; + } + +- **Function Explanation**: This function registers a lookup function based on the table ID. It first checks if the L3 device type is valid, then locks the spinlock to protect the data structure. If a lookup function for the given type already exists, it returns `-EBUSY`. Otherwise, it stores the provided function pointer and unlocks the spinlock. +- **Open Capabilities**: Developers can register their own lookup functions to extend the L3 device lookup logic. + +.. code-block:: c + void l3mdev_table_lookup_unregister(enum l3mdev_type l3type, lookup_by_table_id_t fn) + { + struct l3mdev_handler *hdlr; + + if (l3mdev_check_type(l3type)) + return; + hdlr = &l3mdev_handlers[l3type]; + spin_lock(&l3mdev_lock); + if (hdlr->dev_lookup == fn) + hdlr->dev_lookup = NULL; + spin_unlock(&l3mdev_lock); + } + +- **Function Explanation**: This function unregisters a lookup function based on the table ID. It checks the L3 device type, locks the spinlock, and if the stored function pointer matches the provided one, it sets it to `NULL` and unlocks the spinlock. +- **Open Capabilities**: Developers can unregister previously registered lookup functions to clean up resources or change the lookup logic. + +.. code-block:: c + int l3mdev_ifindex_lookup_by_table_id(enum l3mdev_type l3type, struct net *net, u32 table_id) + { + lookup_by_table_id_t lookup; + struct l3mdev_handler *hdlr; + int ifindex = -EINVAL; + int res; + + res = l3mdev_check_type(l3type); + if (res) + return res; + hdlr = &l3mdev_handlers[l3type]; + spin_lock(&l3mdev_lock); + lookup = hdlr->dev_lookup; + if (!lookup) + goto unlock; + ifindex = lookup(net, table_id); + unlock: + spin_unlock(&l3mdev_lock); + return ifindex; + } + +- **Function Explanation**: This function looks up the device index based on the L3 device type, network namespace, and table ID. It checks the L3 device type, locks the spinlock, and if a lookup function is found, it calls the function and returns the result. If no lookup function is found, it returns `-EINVAL`. +- **Open Capabilities**: Developers can use this function to look up the device index for different L3 device types and table IDs. + +.. code-block:: c + int l3mdev_master_ifindex_rcu(const struct net_device *dev) + { + int ifindex = 0; + if (!dev) + return 0; + if (netif_is_l3_master(dev)) { + ifindex = dev->ifindex; + } else if (netif_is_l3_slave(dev)) { + struct net_device *master; + struct net_device *_dev = (struct net_device *)dev; + master = netdev_master_upper_dev_get_rcu(_dev); + if (master) + ifindex = master->ifindex; + } + return ifindex; + } + +- **Function Explanation**: This function gets the index of the L3 master device. If the device is an L3 master, it returns its index. If the device is an L3 slave, it finds its master and returns the master's index. +- **Open Capabilities**: Developers can determine if a device is an L3 master or slave and get the index of the master device. + +.. code-block:: c + u32 l3mdev_fib_table_rcu(const struct net_device *dev) + { + u32 tb_id = 0; + if (!dev) + return 0; + if (netif_is_l3_master(dev)) { + if (dev->l3mdev_ops->l3mdev_fib_table) + tb_id = dev->l3mdev_ops->l3mdev_fib_table(dev); + } else if (netif_is_l3_slave(dev)) { + struct net_device *_dev = (struct net_device *) dev; + const struct net_device *master; + master = netdev_master_upper_dev_get_rcu(_dev); + if (master && master->l3mdev_ops->l3mdev_fib_table) + tb_id = master->l3mdev_ops->l3mdev_fib_table(master); + } + return tb_id; + } + +- **Function Explanation**: This function retrieves the FIB table ID associated with the L3 master interface. If the device is an L3 master and has a defined `l3mdev_fib_table` function, it calls the function to get the FIB table ID. If the device is a slave, it finds its master and performs the same operation. +- **Open Capabilities**: Developers can query the FIB table associated with the L3 master interface, potentially influencing routing decisions. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/nsh.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/nsh.rst" new file mode 100644 index 0000000000000000000000000000000000000000..3e9a1b19190b6819560080a93ab49bec9de48e1b --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/nsh.rst" @@ -0,0 +1,142 @@ +nsh +==== + +nsh.c (Network Service Header) +------------------------------ + +**Function Description** + +The `nsh.c` file implements the Network Service Header (NSH) protocol, which is part of the Service Function Chaining (SFC) framework. The file includes functions for adding and removing NSH headers and handling Generic Segmentation Offload (GSO) for NSH packets. + +.. code-block:: c + :caption: nsh_push function + + int nsh_push(struct sk_buff *skb, const struct nshhdr *pushed_nh) + { + struct nshhdr *nh; + size_t length = nsh_hdr_len(pushed_nh); + u8 next_proto; + if (skb->mac_len) { + next_proto = TUN_P_ETHERNET; + } else { + next_proto = tun_p_from_eth_p(skb->protocol); + if (!next_proto) + return -EAFNOSUPPORT; + } + if (skb_cow_head(skb, length) < 0) + return -ENOMEM; + skb_push(skb, length); + nh = (struct nshhdr *)(skb->data); + memcpy(nh, pushed_nh, length); + nh->np = next_proto; + skb_postpush_rcsum(skb, nh, length); + skb->protocol = htons(ETH_P_NSH); + skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb_reset_mac_len(skb); + return 0; + } + +- **`nsh_push` function**: This function is responsible for adding an NSH header to the packet. + - It calculates the length of the NSH header to be added. + - Determines the next protocol type based on whether there is a MAC layer length. + - Ensures there is enough space to insert the NSH header using `skb_cow_head`. + - Copies the NSH header information into the packet and updates the relevant protocol fields and pointers. + - Sets the packet's protocol field to `ETH_P_NSH` and resets the MAC and network header pointers. + +.. code-block:: c + :caption: nsh_pop function + + int nsh_pop(struct sk_buff *skb) + { + struct nshhdr *nh; + size_t length; + __be16 inner_proto; + if (!pskb_may_pull(skb, NSH_BASE_HDR_LEN)) + return -ENOMEM; + nh = (struct nshhdr *)(skb->data); + length = nsh_hdr_len(nh); + if (length < NSH_BASE_HDR_LEN) + return -EINVAL; + inner_proto = tun_p_to_eth_p(nh->np); + if (!pskb_may_pull(skb, length)) + return -ENOMEM; + if (!inner_proto) + return -EAFNOSUPPORT; + skb_pull_rcsum(skb, length); + skb_reset_mac_header(skb); + skb_reset_network_header(skb); + skb_reset_mac_len(skb); + skb->protocol = inner_proto; + return 0; + } + +- **`nsh_pop` function**: This function removes the NSH header from the packet. + - Verifies that the packet contains the complete NSH base header length. + - Calculates the total length of the NSH header. + - Checks if the NSH header length is valid. + - Retrieves the inner protocol type and verifies its validity. + - Removes the NSH header and restores the original state of the packet, including updating the protocol field and other related pointers. + +.. code-block:: c + :caption: nsh_gso_segment function + + static struct sk_buff *nsh_gso_segment(struct sk_buff *skb, netdev_features_t features) + { + unsigned int outer_hlen, mac_len, nsh_len; + struct sk_buff *segs = ERR_PTR(-EINVAL); + u16 mac_offset = skb->mac_header; + __be16 outer_proto, proto; + skb_reset_network_header(skb); + outer_proto = skb->protocol; + outer_hlen = skb_mac_header_len(skb); + mac_len = skb->mac_len; + if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN))) + goto out; + nsh_len = nsh_hdr_len(nsh_hdr(skb)); + if (nsh_len < NSH_BASE_HDR_LEN) + goto out; + if (unlikely(!pskb_may_pull(skb, nsh_len))) + goto out; + proto = tun_p_to_eth_p(nsh_hdr(skb)->np); + if (!proto) + goto out; + __skb_pull(skb, nsh_len); + skb_reset_mac_header(skb); + skb->mac_len = proto == htons(ETH_P_TEB) ? ETH_HLEN : 0; + skb->protocol = proto; + features &= NETIF_F_SG; + segs = skb_mac_gso_segment(skb, features); + if (IS_ERR_OR_NULL(segs)) { + skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len, + mac_offset, mac_len); + goto out; + } + for (skb = segs; skb; skb = skb->next) { + skb->protocol = outer_proto; + __skb_push(skb, nsh_len + outer_hlen); + skb_reset_mac_header(skb); + skb_set_network_header(skb, outer_hlen); + skb->mac_len = mac_len; + } + out: + return segs; + } + +- **`nsh_gso_segment` function**: This function handles GSO segmentation for NSH packets. + - Resets the network header pointer. + - Retrieves the outer protocol type and related lengths. + - Checks if there is enough data to contain the complete NSH base header. + - Calculates the total length of the NSH header and verifies its validity. + - Retrieves the inner protocol type and verifies its validity. + - Removes the NSH header and updates the packet's relevant information. + - Calls `skb_mac_gso_segment` to perform GSO segmentation. + - If segmentation fails, it unwinds the operation. + - Restores the NSH header and related pointers for each segment. + +**Open Capabilities** + +- **Custom Header Creation**: Developers can extend the `nsh_push` and `nsh_pop` functions to customize the construction and parsing logic of the NSH header. +- **GSO Segmentation Control**: By implementing or modifying the `nsh_gso_segment` function, developers can adjust the GSO segmentation behavior for NSH packets as needed. +- **Error Handling**: In the `nsh_push` and `nsh_pop` functions, developers can customize error handling logic, such as returning specific error codes or taking other actions. +- **Module Initialization Configuration**: In the `nsh_init_module` function, developers can customize the initial setup of the NSH module, such as registering offload handlers. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/psample.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/psample.rst" new file mode 100644 index 0000000000000000000000000000000000000000..07e9f738034c2ba62d1852868cefa127577904e4 --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/psample.rst" @@ -0,0 +1,71 @@ +psample +=========== + +### psample.c (Packet Sampling) +------------------------------- + +**Function Description** +The `psample.c` file implements a Netlink channel for packet sampling, which allows transferring packets alongside some metadata to userspace. It includes group management and data transmission logic. + +.. code-block:: c + + static int psample_group_nl_fill(struct sk_buff *msg, + struct psample_group *group, + enum psample_command cmd, + u32 portid, u32 seq, int flags) + { + void *hdr; + int ret; + hdr = genlmsg_put(msg, portid, seq, &psample_nl_family, flags, cmd); + if (!hdr) + return -EMSGSIZE; + ret = nla_put_u32(msg, PSAMPLE_ATTR_SAMPLE_GROUP, group->group_num); + if (ret < 0) + goto error; + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_REFCOUNT, group->refcount); + if (ret < 0) + goto error; + ret = nla_put_u32(msg, PSAMPLE_ATTR_GROUP_SEQ, group->seq); + if (ret < 0) + goto error; + genlmsg_end(msg, hdr); + return 0; + error: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; + } + +This function fills a Netlink message with information about a specific sample group and sends it to userspace. It uses `genlmsg_put` and `nla_put_u32` to construct and add necessary attributes. + +.. code-block:: c + + void psample_sample_packet(struct psample_group *group, struct sk_buff *skb, + u32 trunc_size, int in_ifindex, int out_ifindex, + u32 sample_rate) + { + data_len = min(skb->len, trunc_size); + if (meta_len + nla_total_size(data_len) > PSAMPLE_MAX_PACKET_SIZE) + data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN - NLA_ALIGNTO; + + nl_skb = genlmsg_new(meta_len + nla_total_size(data_len), GFP_ATOMIC); + if (unlikely(!nl_skb)) + return; + data = genlmsg_put(nl_skb, 0, 0, &psample_nl_family, 0, PSAMPLE_CMD_SAMPLE); + if (unlikely(!data)) + goto error; + genlmsg_multicast_netns(&psample_nl_family, group->net, nl_skb, 0, + PSAMPLE_NL_MCGRP_SAMPLE, GFP_ATOMIC); + return; + error: + pr_err_ratelimited("Could not create psample log message\n"); + nlmsg_free(nl_skb); + } + +The `psample_sample_packet` function creates a new Netlink message containing the truncated packet data and associated metadata, and multicasts it to all user-space processes listening to the sample group. + +**Open Capabilities** +- **Custom Message Filling**: Developers can extend the `psample_group_nl_fill` function to customize the message content sent to userspace. +- **Sample Packet Handling**: The `psample_sample_packet` function allows developers to customize how sample packets and their metadata are handled. +- **Group Management**: Functions such as `psample_group_create`, `psample_group_destroy`, and `psample_group_lookup` provide the ability to create, destroy, and look up sample groups. +- **State Notification**: The `psample_group_notify` function can be used to notify userspace when the state of a sample group changes. +- **Query Interface**: The `psample_nl_cmd_get_group_dumpit` function provides an interface for querying all existing sample groups and their states. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/qrtr.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/qrtr.rst" new file mode 100644 index 0000000000000000000000000000000000000000..8ab2f33b8e50773fbd8f91f03b3c57fa810c0efe --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/qrtr.rst" @@ -0,0 +1,436 @@ +This document provides a detailed breakdown of the functionalities in the provided source code snippets, covering various aspects of the Qualcomm IPC Router (QRTR) including configuration, transport mechanisms, and network services. The analysis is based on the source files: `Kconfig`, `Makefile`, `mhi.c`, `ns.c`, `qrtr.c`, `qrtr.h`, `smd.c`, and `tun.c`. + +Configuration (Kconfig) +---------------------- +The `Kconfig` file allows for the selection of different components of the QRTR protocol to be compiled into the kernel or as loadable modules. + +Configuration Options +~~~~~~~~~~~~~~~~~~~~ +- **QRTR** - Support for the Qualcomm IPC Router protocol. + - **QRTR_SMD** - Support for SMD (Shared Memory Driver) based IPC router channels. This is the most common transport for IPC Router. + - **QRTR_TUN** - Expose a TUN device that allows user space to implement endpoints of QRTR, for the purpose of tunneling data to other hosts or testing. + - **QRTR_MHI** - Support for MHI (Modem Host Interface) based IPC router channels, used for communicating with external modems. + +Build System (Makefile) +----------------------- +The `Makefile` specifies how the QRTR components are built. It defines which object files should be included when the corresponding configuration options are enabled. + +Object Files +~~~~~~~~~~~~ +- **obj-$(CONFIG_QRTR)**: Main QRTR objects, including `qrtr.o` and `ns.o`. +- **obj-$(CONFIG_QRTR_SMD)**: SMD transport objects, including `qrtr-smd.o` and `smd.o`. +- **obj-$(CONFIG_QRTR_TUN)**: TUN device objects, including `qrtr-tun.o` and `tun.o`. +- **obj-$(CONFIG_QRTR_MHI)**: MHI transport objects, including `qrtr-mhi.o` and `mhi.o`. + +MHI Transport (mhi.c) +--------------------- +The MHI (Modem Host Interface) transport layer is used for communicating with external modems. + +Key Functions +~~~~~~~~~~~~~ +- **qcom_mhi_qrtr_probe**: Initializes the MHI QRTR endpoint and registers it. + + .. code-block:: c + + static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev) + { + struct qrtr_mhi_dev *qdev; + int rc; + + qdev = devm_kzalloc(&mhi_dev->dev, sizeof(*qdev), GFP_KERNEL); + if (!qdev) + return -ENOMEM; + + qdev->mhi_dev = mhi_dev; + qdev->dev = &mhi_dev->dev; + dev_set_drvdata(&mhi_dev->dev, qdev); + + rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO); + if (rc) + return rc; + + dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n"); + return 0; + } + +- **qcom_mhi_qrtr_send**: Sends data over MHI. + + .. code-block:: c + + static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb) + { + struct qrtr_mhi_dev *qdev = container_of(ep, struct qrtr_mhi_dev, ep); + int rc; + + if (skb->sk) + sock_hold(skb->sk); + + rc = skb_linearize(skb); + if (rc) + goto free_skb; + + rc = mhi_queue_skb(qdev->mhi_dev, DMA_TO_DEVICE, skb, skb->len, MHI_EOT); + if (rc) + goto free_skb; + + return rc; + + free_skb: + kfree_skb(skb); + return rc; + } + +- **qcom_mhi_qrtr_dl_callback**: Handles incoming data from MHI. + + .. code-block:: c + + static void qcom_mhi_qrtr_dl_callback(struct mhi_device *mhi_dev, + struct mhi_result *mhi_res) + { + struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev); + int rc; + + if (!qdev || mhi_res->transaction_status) + return; + + rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr, mhi_res->bytes_xferd); + if (rc == -EINVAL) + dev_err(qdev->dev, "invalid ipcrouter packet\n"); + } + +- **qcom_mhi_qrtr_ul_callback**: Handles outgoing data to MHI. + + .. code-block:: c + + static void qcom_mhi_qrtr_ul_callback(struct mhi_device *mhi_dev, + struct mhi_result *mhi_res) + { + struct sk_buff *skb = mhi_res->buf_addr; + if (skb->sk) + sock_put(skb->sk); + consume_skb(skb); + } + +Network Services (ns.c) +----------------------- +Handles service discovery and registration for QRTR. + +Key Functions +~~~~~~~~~~~~~ +- **qrtr_ns_init**: Initializes the QRTR namespace, including setting up work queues and sockets. + + .. code-block:: c + + void qrtr_ns_init(void) + { + struct sockaddr_qrtr sq; + int ret; + + INIT_LIST_HEAD(&qrtr_ns.lookups); + INIT_WORK(&qrtr_ns.work, qrtr_ns_worker); + + ret = sock_create_kern(&init_net, AF_QIPCRTR, SOCK_DGRAM, PF_QIPCRTR, &qrtr_ns.sock); + if (ret < 0) + return; + + ret = kernel_getsockname(qrtr_ns.sock, (struct sockaddr *)&sq); + if (ret < 0) { + pr_err("failed to get socket name\n"); + goto err_sock; + } + + qrtr_ns.workqueue = alloc_workqueue("qrtr_ns_handler", WQ_UNBOUND, 1); + if (!qrtr_ns.workqueue) { + ret = -ENOMEM; + goto err_sock; + } + + qrtr_ns.sock->sk->sk_data_ready = qrtr_ns_data_ready; + sq.sq_port = QRTR_PORT_CTRL; + qrtr_ns.local_node = sq.sq_node; + + ret = kernel_bind(qrtr_ns.sock, (struct sockaddr *)&sq, sizeof(sq)); + if (ret < 0) { + pr_err("failed to bind to socket\n"); + goto err_wq; + } + + qrtr_ns.bcast_sq.sq_family = AF_QIPCRTR; + qrtr_ns.bcast_sq.sq_node = QRTR_NODE_BCAST; + qrtr_ns.bcast_sq.sq_port = QRTR_PORT_CTRL; + + ret = say_hello(&qrtr_ns.bcast_sq); + if (ret < 0) + goto err_wq; + + return; + + err_wq: + destroy_workqueue(qrtr_ns.workqueue); + err_sock: + sock_release(qrtr_ns.sock); + } + +- **qrtr_ns_remove**: Cleans up the resources associated with the QRTR namespace. + + .. code-block:: c + + void qrtr_ns_remove(void) + { + cancel_work_sync(&qrtr_ns.work); + destroy_workqueue(qrtr_ns.workqueue); + sock_release(qrtr_ns.sock); + } + +- **qrtr_ns_worker**: Worker function that processes incoming control packets. + + .. code-block:: c + + static void qrtr_ns_worker(struct work_struct *work) + { + const struct qrtr_ctrl_pkt *pkt; + size_t recv_buf_size = 4096; + struct sockaddr_qrtr sq; + struct msghdr msg = { }; + unsigned int cmd; + ssize_t msglen; + void *recv_buf; + struct kvec iv; + int ret; + + msg.msg_name = (struct sockaddr *)&sq; + msg.msg_namelen = sizeof(sq); + recv_buf = kzalloc(recv_buf_size, GFP_KERNEL); + if (!recv_buf) + return; + + for (;;) { + iv.iov_base = recv_buf; + iv.iov_len = recv_buf_size; + msglen = kernel_recvmsg(qrtr_ns.sock, &msg, &iv, 1, iv.iov_len, MSG_DONTWAIT); + if (msglen == -EAGAIN) + break; + if (msglen < 0) { + pr_err("error receiving packet: %zd\n", msglen); + break; + } + + pkt = recv_buf; + cmd = le32_to_cpu(pkt->cmd); + if (cmd < ARRAY_SIZE(qrtr_ctrl_pkt_strings) && qrtr_ctrl_pkt_strings[cmd]) + trace_qrtr_ns_message(qrtr_ctrl_pkt_strings[cmd], sq.sq_node, sq.sq_port); + + ret = 0; + switch (cmd) { + case QRTR_TYPE_HELLO: + ret = ctrl_cmd_hello(&sq); + break; + // Other cases... + } + if (ret < 0) + pr_err("failed while handling packet from %d:%d", sq.sq_node, sq.sq_port); + } + kfree(recv_buf); + } + +Core Protocol (qrtr.c) +---------------------- +Implements the core functionality of the QRTR protocol, including socket operations and packet handling. + +Key Functions +~~~~~~~~~~~~~ +- **qrtr_create**: Creates a new QRTR socket. + + .. code-block:: c + + static int qrtr_create(struct net *net, struct socket *sock, int protocol, bool kern) + { + struct qrtr_sock *ipc; + struct sock *sk; + + + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; + + sock_set_flag(sk, SOCK_ZAPPED); + sock_init_data(sock, sk); + sock->ops = &qrtr_proto_ops; + ipc = qrtr_sk(sk); + ipc->us.sq_family = AF_QIPCRTR; + ipc->us.sq_node = qrtr_local_nid; + ipc->us.sq_port = 0; + return 0; + } + + +- **qrtr_sendmsg/recvmsg**: Send and receive messages through the QRTR socket. + + .. code-block:: c + + static int qrtr_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) + { + struct sock *sk = sock->sk; + struct qrtr_sock *ipc = qrtr_sk(sk); + struct sockaddr_qrtr *to = (struct sockaddr_qrtr *)msg->msg_name; + struct sk_buff *skb; + int ret; + + if (len < sizeof(struct qrtr_hdr_v1)) + return -EINVAL; + + if (msg->msg_flags & MSG_OOB) + return -EOPNOTSUPP; + + skb = __netdev_alloc_skb(NULL, len, GFP_ATOMIC | __GFP_NOWARN); + if (!skb) + return -ENOMEM; + + ret = memcpy_from_msg(skb_put(skb, len), msg, len); + if (ret < 0) { + kfree_skb(skb); + return ret; + } + + if (to) { + ret = qrtr_ep_send(ipc->ep, to->sq_node, to->sq_port, skb); + } else { + ret = qrtr_ep_send(ipc->ep, ipc->us.sq_node, ipc->us.sq_port, skb); + } + + if (ret < 0) + kfree_skb(skb); + + return ret ? ret : len; + } + + static int qrtr_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) + { + struct sock *sk = sock->sk; + struct qrtr_sock *ipc = qrtr_sk(sk); + struct sk_buff *skb; + int copied, ret; + + skb = skb_recv_datagram(sk, flags, &ret); + if (!skb) + return ret; + + copied = skb_copy_datagram_msg(skb, 0, msg, len); + kfree_skb(skb); + + return copied; + } + +Header Definitions (qrtr.h) +--------------------------- +Provides the necessary definitions and structures for the QRTR protocol. + +Key Structures +~~~~~~~~~~~~~~ +- **struct qrtr_endpoint**: Represents an endpoint in the QRTR system. + + .. code-block:: c + + struct qrtr_endpoint { + int (*xmit)(struct qrtr_endpoint *ep, struct sk_buff *skb); + /* private: not for endpoint use */ + struct qrtr_node *node; + }; + +- **struct sockaddr_qrtr**: Used for addressing in the QRTR protocol. + + .. code-block:: c + + struct sockaddr_qrtr { + sa_family_t sq_family; /* AF_QIPCRTR */ + unsigned int sq_node; /* Node ID */ + unsigned int sq_port; /* Port number */ + }; + +- **qrtr_ctrl_pkt_strings**: Array of strings representing control packet types. + + .. code-block:: c + + static const char *const qrtr_ctrl_pkt_strings[] = { + [QRTR_TYPE_HELLO] = "hello", + [QRTR_TYPE_BYE] = "bye", + [QRTR_TYPE_NEW_SERVER] = "new-server", + [QRTR_TYPE_DEL_SERVER] = "del-server", + [QRTR_TYPE_DEL_CLIENT] = "del-client", + [QRTR_TYPE_RESUME_TX] = "resume-tx", + [QRTR_TYPE_EXIT] = "exit", + [QRTR_TYPE_PING] = "ping", + [QRTR_TYPE_NEW_LOOKUP] = "new-lookup", + [QRTR_TYPE_DEL_LOOKUP] = "del-lookup", + }; + +SMD Transport (smd.c) +--------------------- +Manages the SMD-based transport for QRTR. + +Key Functions +~~~~~~~~~~~~~ +- **qcom_smd_qrtr_probe**: Initializes the SMD QRTR endpoint. + + .. code-block:: c + + static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev) + { + struct qrtr_smd_dev *qdev; + int rc; + + qdev = devm_kzalloc(&rpdev->dev, sizeof(*qdev), GFP_KERNEL); + if (!qdev) + return -ENOMEM; + + qdev->channel = rpdev->ept; + qdev->dev = &rpdev->dev; + dev_set_drvdata(&rpdev->dev, qdev); + + rc = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NID_AUTO); + if (rc) + return rc; + + dev_dbg(qdev->dev, "Qualcomm SMD QRTR driver probed\n"); + return 0; + } + +- **qcom_smd_qrtr_send**: Sends data over SMD. + + .. code-block:: c + + static int qcom_smd_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb) + { + struct qrtr_smd_dev *qdev = container_of(ep, struct qrtr_smd_dev, ep); + int rc; + + if (skb->sk) + sock_hold(skb->sk); + + rc = skb_linearize(skb); + if (rc) + goto free_skb; + + rc = rpmsg_send(qdev->channel, skb->data, skb->len); + if (rc) + goto free_skb; + + return 0; + + free_skb: + kfree_skb(skb); + return rc; + } + +Developer Open Capabilities +--------------------------- +QRTR provides several open capabilities to developers, enabling them to integrate and extend the functionality of the protocol. These include: + +- **Socket API**: Developers can create, bind, connect, and communicate using QRTR sockets. The socket API is similar to standard BSD sockets but tailored for the QRTR protocol. +- **TUN Device**: By exposing a TUN device, QRTR allows user space applications to act as endpoints. This is particularly useful for testing and development, as well as for implementing custom protocols or tunnels. +- **Service Discovery**: QRTR includes a nameservice (NS) that allows services to register and be discovered by other components in the system. This enables dynamic service lookup and management. +- **Transport Flexibility**: QRTR supports multiple transport mechanisms, such as SMD and MHI, allowing developers to choose the most appropriate transport for their use case. +- **Custom Endpoints**: Developers can implement custom endpoints by registering and managing their own `qrtr_endpoint` structures, providing flexibility in how data is handled and processed. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/rfkill.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/rfkill.rst" new file mode 100644 index 0000000000000000000000000000000000000000..1901a23229a34eb7337486a116adc34ac7e5457a --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/rfkill.rst" @@ -0,0 +1,198 @@ +rfkill +=========== + +core.c (RF Switch Core) +----------------------- +**Function Description** +The `core.c` file implements the core functionalities for the RF switch subsystem, including state management and event handling for RF switches. It defines the `struct rfkill` and related operations. + +.. code-block:: c + + struct rfkill { + spinlock_t lock; + enum rfkill_type type; + unsigned long state; + u32 idx; + bool registered; + bool persistent; + bool polling_paused; + bool suspended; + const struct rfkill_ops *ops; + void *data; + #ifdef CONFIG_RFKILL_LEDS + struct led_trigger led_trigger; + const char *ledtrigname; + #endif + struct device dev; + struct list_head node; + struct delayed_work poll_work; + struct work_struct uevent_work; + struct work_struct sync_work; + char name[]; + }; + +- **State Management**: Manages the hardware and software states of RF switches. +- **Event Handling**: Handles events such as changes in the state of RF switches and triggers appropriate actions. + +**Open Capabilities** +- **Custom State Management**: Developers can extend the state management by implementing their own `rfkill_ops` structure, which includes functions like `poll`, `set_block`, and `query`. +- **Device Registration**: Through the `rfkill_register` function, developers can register their own RF switch devices with the system. +- **LED Trigger Support**: If LED support is enabled, developers can customize the behavior of LEDs using the `led_trigger` structure. + +.. code-block:: c + + int __must_check rfkill_register(struct rfkill *rfkill) { + } + + void rfkill_unregister(struct rfkill *rfkill) { + } + + void rfkill_destroy(struct rfkill *rfkill) { + } + +Kconfig (Configuration) +----------------------- +**Function Description** +The `Kconfig` file allows users to configure the RF switch subsystem via the kernel configuration tool. It enables or disables the subsystem and its optional features, such as LED trigger support and input handling. + +.. code-block:: none + + menuconfig RFKILL + tristate "RF switch subsystem support" + help + Say Y here if you want to have control over RF switches found on many WiFi and Bluetooth cards. + +**Open Capabilities** +- **Configurable Subsystem**: Users can enable or disable the RF switch subsystem and its features, allowing for flexibility in kernel configurations. + +rfkill.h (Header File) +---------------------- +**Function Description** +The `rfkill.h` header file defines the API for the RF switch subsystem, including functions for global switch operations, emergency power-off, and state restoration. + +.. code-block:: c + + void rfkill_switch_all(const enum rfkill_type type, bool blocked); + void rfkill_epo(void); + void rfkill_restore_states(void); + +**Open Capabilities** +- **API Access**: Developers can use the provided API to control all RF switches, perform an emergency power-off, and restore states, allowing for high-level control over the subsystem. + +rfkill-gpio.c (GPIO RF Kill Driver) +----------------------------------- +**Function Description** +The `rfkill-gpio.c` file provides a generic GPIO-based RF kill driver. It handles the initialization, probing, and removal of GPIO-based RF switches. + +.. code-block:: c + + static int rfkill_gpio_probe(struct platform_device *pdev) { + struct rfkill_gpio_data *rfkill; + struct gpio_desc *gpio; + const char *type_name; + int ret; + + rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL); + if (!rfkill) + return -ENOMEM; + + device_property_read_string(&pdev->dev, "name", &rfkill->name); + device_property_read_string(&pdev->dev, "type", &type_name); + if (!rfkill->name) + rfkill->name = dev_name(&pdev->dev); + + rfkill->type = rfkill_find_type(type_name); + if (ACPI_HANDLE(&pdev->dev)) { + ret = rfkill_gpio_acpi_probe(&pdev->dev, rfkill); + if (ret) + return ret; + } + + rfkill->clk = devm_clk_get(&pdev->dev, NULL); + gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + rfkill->reset_gpio = gpio; + + gpio = devm_gpiod_get_optional(&pdev->dev, "shutdown", GPIOD_OUT_LOW); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + rfkill->shutdown_gpio = gpio; + + if (!rfkill->reset_gpio && !rfkill->shutdown_gpio) { + dev_err(&pdev->dev, "invalid platform data\n"); + return -EINVAL; + } + + rfkill->rfkill_dev = rfkill_alloc(rfkill->name, &pdev->dev, + rfkill->type, &rfkill_gpio_ops, + rfkill); + if (!rfkill->rfkill_dev) + return -ENOMEM; + + ret = rfkill_register(rfkill->rfkill_dev); + if (ret < 0) + goto err_destroy; + + platform_set_drvdata(pdev, rfkill); + dev_info(&pdev->dev, "%s device registered.\n", rfkill->name); + return 0; + + err_destroy: + rfkill_destroy(rfkill->rfkill_dev); + return ret; + } + + static int rfkill_gpio_remove(struct platform_device *pdev) { + struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); + rfkill_unregister(rfkill->rfkill_dev); + rfkill_destroy(rfkill->rfkill_dev); + return 0; + } + +**Open Capabilities** +- **GPIO Customization**: Developers can customize the GPIO-based RF switch driver to work with specific hardware, including setting up GPIOs and handling probe and remove operations. +- **Platform Device Support**: The driver integrates with the platform device framework, making it easy to add support for new hardware. + +input.c (Input Layer Interface) +------------------------------- +**Function Description** +The `input.c` file provides an interface between the RF switch subsystem and the input layer. It handles input events and translates them into RF switch commands. + +.. code-block:: c + + static struct input_handler rfkill_handler = { + .name = "rfkill", + .event = rfkill_event, + .connect = rfkill_connect, + .start = rfkill_start, + .disconnect = rfkill_disconnect, + .id_table = rfkill_ids, + }; + + static void rfkill_event(struct input_handle *handle, unsigned int type, + unsigned int code, int data) { + if (type == EV_KEY && data == 1) { + switch (code) { + case KEY_WLAN: + rfkill_schedule_toggle(RFKILL_TYPE_WLAN); + break; + case KEY_BLUETOOTH: + rfkill_schedule_toggle(RFKILL_TYPE_BLUETOOTH); + break; + case KEY_UWB: + rfkill_schedule_toggle(RFKILL_TYPE_UWB); + break; + case KEY_WIMAX: + rfkill_schedule_toggle(RFKILL_TYPE_WIMAX); + break; + case KEY_RFKILL: + rfkill_schedule_toggle(RFKILL_TYPE_ALL); + break; + } + } else if (type == EV_SW && code == SW_RFKILL_ALL) + rfkill_schedule_evsw_rfkillall(data); + } + +**Open Capabilities** +- **Input Event Handling**: Developers can extend the input handler to handle custom input events and translate them into RF switch commands, providing a flexible way to interact with the RF switch subsystem. \ No newline at end of file diff --git "a/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/rose.rst" "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/rose.rst" new file mode 100644 index 0000000000000000000000000000000000000000..b3a8dcafc384a205459e4dcafdcae94dd4ca0abe --- /dev/null +++ "b/OpenEuler(version_20.09\357\274\21422.03-LTS-SP1)_documentation_supplement/version_22.03-LTS-SP1_documentation_supplement/rose.rst" @@ -0,0 +1,320 @@ +.. ROSE Code Explanation +===================== + + +Device Management - ``rose_dev.c`` +---------------------------------- + +**Function Description** +The ``rose_dev.c`` file deals with the creation and configuration of virtual ROSE network devices. These devices are used to encapsulate ROSE frames into AX.25 frames, which are then transmitted over an AX.25 device. + +### Key Functions +- **rose_setup()**: Initializes a ROSE network device. +- **rose_open()**: Opens the ROSE network device. +- **rose_close()**: Closes the ROSE network device. +- **rose_xmit()**: Handles the transmission of data packets. + +.. code-block:: c + + void rose_setup(struct net_device *dev) + { + dev->mtu = ROSE_MAX_PACKET_SIZE - 2; + dev->netdev_ops = &rose_netdev_ops; + dev->header_ops = &rose_header_ops; + dev->hard_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; + dev->addr_len = ROSE_ADDR_LEN; + dev->type = ARPHRD_ROSE; + dev->flags = IFF_NOARP; + } + + static int rose_open(struct net_device *dev) + { + // ... + } + + static int rose_close(struct net_device *dev) + { + // ... + } + + static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev) + { + // ... + } + +**Developer Open Capabilities** +- Developers can create and manage ROSE network devices. +- They can configure the MTU and other parameters of ROSE devices. +- Applications can send and receive data over ROSE devices using standard networking APIs. + +Incoming Frame Processing - ``rose_in.c`` +------------------------------------------ + +**Function Description** +The ``rose_in.c`` file processes incoming ROSE frames. It includes the state machine that handles different states of the connection and the actions taken based on the received frame type. + +### Key Functions +- **rose_process_rx_frame()**: Processes an incoming frame. +- **rose_state1_machine()**: State machine for awaiting call accepted state. +- **rose_enquiry_response()**: Sends an enquiry response. + +.. code-block:: c + + int rose_process_rx_frame(struct sock *sk, struct sk_buff *skb) + { + struct rose_sock *rose = rose_sk(sk); + int queued = 0, frametype, ns, nr, q, d, m; + if (rose->state == ROSE_STATE_0) + return 0; + frametype = rose_decode(skb, &ns, &nr, &q, &d, &m); + switch (rose->state) { + case ROSE_STATE_1: + queued = rose_state1_machine(sk, skb, frametype); + break; + // ... + } + rose_kick(sk); + return queued; + } + + static int rose_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) + { + struct rose_sock *rose = rose_sk(sk); + switch (frametype) { + case ROSE_CALL_ACCEPTED: + rose->state = ROSE_STATE_3; + rose_start_idletimer(sk); + rose_write_internal(sk, ROSE_DATA); + break; + case ROSE_RESET_REQUEST: + rose_write_internal(sk, ROSE_RESET_CONFIRMATION); + rose->condition = 0x00; + rose->vs = 0; + rose->vr = 0; + rose->va = 0; + rose->vl = 0; + rose->state = ROSE_STATE_4; + rose_start_t2timer(sk); + rose_stop_idletimer(sk); + break; + // ... + } + return 0; + } + + void rose_enquiry_response(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + if (rose->condition & ROSE_COND_OWN_RX_BUSY) + rose_write_internal(sk, ROSE_RNR); + else + rose_write_internal(sk, ROSE_RR); + rose->vl = rose->vr; + rose->condition &= ~ROSE_COND_ACK_PENDING; + rose_stop_timer(sk); + } + +**Developer Open Capabilities** +- Developers can extend or modify the state machine to handle custom frame types or additional states. +- They can implement custom logic for handling specific frame types. +- Applications can monitor and respond to incoming frames using the provided state machine and functions. + +Outgoing Frame Processing - ``rose_out.c`` +------------------------------------------- + +**Function Description** +The ``rose_out.c`` file manages the sending of outgoing ROSE frames. This includes building the control part of the frame and transmitting it through the appropriate link. + +### Key Functions +- **rose_send_iframe()**: Builds and sends an information frame. +- **rose_kick()**: Initiates the transmission of pending data. + +.. code-block:: c + + static void rose_send_iframe(struct sock *sk, struct sk_buff *skb) + { + struct rose_sock *rose = rose_sk(sk); + if (skb == NULL) + return; + skb->data[2] |= (rose->vr << 5) & 0xE0; + skb->data[2] |= (rose->vs << 1) & 0x0E; + rose_start_idletimer(sk); + rose_transmit_link(skb, rose->neighbour); + } + + void rose_kick(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + struct sk_buff *skb, *skbn; + unsigned short start, end; + + if (rose->state != ROSE_STATE_3) + return; + if (rose->condition & ROSE_COND_PEER_RX_BUSY) + return; + if (!skb_peek(&sk->sk_write_queue)) + return; + + start = (skb_peek(&rose->ack_queue) == NULL) ? rose->va : rose->vs; + end = (rose->va + sysctl_rose_window_size) % ROSE_MODULUS; + if (start == end) + return; + + rose->vs = start; + skb = skb_dequeue(&sk->sk_write_queue); + do { + if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { + skb_queue_head(&sk->sk_write_queue, skb); + break; + } + skb_set_owner_w(skbn, sk); + rose_send_iframe(sk, skbn); + rose->vs = (rose->vs + 1) % ROSE_MODULUS; + skb_queue_tail(&rose->ack_queue, skb); + } while (rose->vs != end && (skb = skb_dequeue(&sk->sk_write_queue)) != NULL); + rose->vl = rose->vr; + rose->condition &= ~ROSE_COND_ACK_PENDING; + rose_stop_timer(sk); + } + +**Developer Open Capabilities** +- Developers can customize the frame construction process to include additional headers or data. +- They can implement custom logic for managing the transmission window and retransmissions. +- Applications can send data over ROSE sockets using standard socket APIs, and the underlying mechanisms will handle the frame construction and transmission. + +Routing - ``rose_route.c`` +-------------------------- + +**Function Description** +The ``rose_route.c`` file is responsible for managing routes and neighbors. It includes functions to add, remove, and update routes, as well as to manage neighbor relationships. + +### Key Functions +- **rose_add_node()**: Adds a new route to a node. +- **rose_find_socket()**: Finds a socket associated with a Logical Channel Identifier (LCI). +- **rose_add_neigh()**: Adds a new neighbor. + +.. code-block:: c + + static int __must_check rose_add_node(struct rose_route_struct *rose_route, + struct net_device *dev) + { + // ... + } + + struct sock *rose_find_socket(unsigned int lci, struct rose_neigh *neigh) + { + // ... + } + + static int rose_add_neigh(struct rose_neigh *neigh) + { + // ... + } + +**Developer Open Capabilities** +- Developers can add, remove, and manage routes and neighbors programmatically. +- They can extend the routing logic to support custom routing algorithms. +- Applications can query and manipulate the routing table and neighbor list using provided functions. + +Timer Management - ``rose_timer.c`` +------------------------------------ + +**Function Description** +The ``rose_timer.c`` file handles the management of timers, including the expiration of timers and the actions to take when a timer expires. Timers are used for various purposes, such as heartbeat monitoring and retransmission timeouts. + +### Key Functions +- **rose_start_t1timer()**: Starts the T1 timer. +- **rose_start_t2timer()**: Starts the T2 timer. +- **rose_timer_expiry()**: Handles the expiration of a timer. + +.. code-block:: c + + void rose_start_t1timer(struct sock *sk) + { + struct rose_sock *rose = rose_sk(sk); + sk_stop_timer(sk, &rose->timer); + rose->timer.function = rose_timer_expiry; + rose->timer.expires = jiffies + rose->t1; + sk_reset_timer(sk, &rose->timer, rose->timer.expires); + } + + static void rose_timer_expiry(struct timer_list *t) + { + struct rose_sock *rose = from_timer(rose, t, timer); + struct sock *sk = &rose->sock; + bh_lock_sock(sk); + switch (rose->state) { + case ROSE_STATE_1: // T1 + case ROSE_STATE_4: // T2 + rose_write_internal(sk, ROSE_CLEAR_REQUEST); + rose->state = ROSE_STATE_2; + rose_start_t3timer(sk); + break; + case ROSE_STATE_2: // T3 + rose->neighbour->use--; + rose_disconnect(sk, ETIMEDOUT, -1, -1); + break; + case ROSE_STATE_3: // HB + if (rose->condition & ROSE_COND_ACK_PENDING) { + rose->condition &= ~ROSE_COND_ACK_PENDING; + rose_enquiry_response(sk); + } + break; + } + bh_unlock_sock(sk); + sock_put(sk); + } + +**Developer Open Capabilities** +- Developers can customize the timer behavior and expiration actions. +- They can implement additional timers for custom functionality. +- Applications can rely on the built-in timer mechanisms to manage connection states and retransmissions. + +System Control - ``sysctl_net_rose.c`` +--------------------------------------- + +**Function Description** +The ``sysctl_net_rose.c`` file provides sysctl interfaces for configuring and controlling the behavior of the ROSE protocol. It allows users to adjust parameters such as timeout values and maximum virtual circuits. + +### Key Functions +- **sysctl_rose_restart_request_timeout**: Controls the restart request timeout. +- **sysctl_rose_call_request_timeout**: Controls the call request timeout. +- **sysctl_rose_clear_request_timeout**: Controls the clear request timeout. + +.. code-block:: c + + static struct ctl_table rose_table[] = { + { + .procname = "restart_request_timeout", + .data = &sysctl_rose_restart_request_timeout, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &min_timer, + .extra2 = &max_timer + }, + { + .procname = "call_request_timeout", + .data = &sysctl_rose_call_request_timeout, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &min_timer, + .extra2 = &max_timer + }, + { + .procname = "clear_request_timeout", + .data = &sysctl_rose_clear_request_timeout, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &min_timer, + .extra2 = &max_timer + }, + //... + }; + +**Developer Open Capabilities** +- Developers can adjust the behavior of the ROSE protocol by modifying sysctl parameters. +- They can expose additional sysctl parameters for custom settings. +- Applications can read and write sysctl parameters to dynamically configure the ROSE protocol at runtime. \ No newline at end of file