## 4 Implementation
### Lightweight IO Visor-Based Packet Tracing for Security-Enhanced Visibility  
Before enabling IO Visor-based packet tracing and collection, it is essential to verify that the target server's Linux kernel supports eBPF, which is the case for any kernel version beginning with version 4.4.10, and that BCC tools/libraries are installed. This setup allows any Linux socket to be attached using user-defined tracing criteria. Such criteria are defined using the user-space program, through high-level programming such as Python. It is easier to write a BPF program with additional kernel instrumentation in C.  
Our implementation of IO Visor-based packet tracing collects data from the network interfaces of Linux servers by attaching our user-space program to a Linux networking socket. Once attached, it starts tracing packet data based on the specified criteria within our program. Kernel networking I/O processes only incoming or outgoing packets that match with the criteria, and sends the traced data in raw bytes to the user-space program. Additionally, we also attach our program into the TCP kernel function to further trace data that contain specific TCP header information. This provides more kernel-specific details related to the TCP packet. The first implementation of our IO Visor-based packet tracing is BPF code definition. For base collection, we define specific tracing criteria for collecting raw bytes from the 5-tuples of the IP-only packet. It traces all raw bytes of packet headers (i.e., Ethernet, IP,  
Figure 5: Design of ONOS intent-leveraged networking control. and TCP) and payloads, and only processes raw bytes that match with the criteria (i.e., 0x0800 is IP packet, 0x06 is TCP packet, and other criterion). It ensures that required fields are available before it sends the whole packet information into the user-space program. For TCP-sync collection, we define criteria to trace only the SYN-type of TCP connection from the packet header. It sends only traced packets to the user-space program for further processing and delivery. The detailed algorithms that logically implement our BPF programs are shown as Algorithms 1 and 2 for base collection and for TCP-sync collection. ```
1:Input:\(p\)\(\triangleright\)\(p\) = packet buffer
2:procedureBaseTracing(\(p\))
3:if\(p.\)ethtype \(\
eq\) IP then
4: Drop the packet \(p\)
5:else
6:if\(p.\)ip.nextproto \(\
eq\) TCP & \(p.\)ip.nextproto \(\
eq\) UDP then
7: Drop the packet \(p\)
8:else
9: Send the packet \(p\) to user-space
10:endif
11:endif
12:endprocedure
13:Output:\(packetp\)\(\triangleright\) 5-tuples containing packet
```  
**Algorithm 1** Packet tracing for Base Collection  
The second implementation is a Python-based program that runs in the user space. This program calls or loads the BPF programs by compiling them with LLVM, attaching to kernel space with the help of the BCC library, and hooking them as interpreted bytecode into the kernel hook point. For base collection, the Python program uses socket programming to hook the BPF programs into the Linux networking socket. All raw bytes of packet data received from that socket are translated into byte arrays. The same program extracts 5-tuples information from the packet by scanning and locating a specific range of arrays from the whole byte arrays, as shown in Listing 1. Similarly, for TCP-sync collection, a Python program is also hooked into the Linux networking socket, but it only extracts three piecesof information from a specific range of byte arrays to detect different TCP SYN messages communication in the Linux server.