 I'm Hanmin Liu from Red Hat. I'm working in the network service team. And today we will talk about how to start programming with FDP. Okay. So, here's the agenda. First, we will talk about what and why use FDP. And then we will write a small program. We will extend the program and use the BPF maps. At last, we will load the BPF program with BPF. Okay. First, what and why we use FDP. As the time is limited, we will go through this part quickly. So, what's FDP? FDP, in case of express data test, is a network feature based on EPPF. It's very easy to use because we can comply it once and load it on multi-cernels without recombining. And it's also very fast. And we can operate on package before it's being converted to SKB and go through the whole network stack. Okay. Now, let's see how to write a hardware program. The first two lines is the helper functions. It provides the helper functions. And the next is the section helper. This is used to place a section in the ELF file after combining. Here, we define the section name as FDP job. The next line is the main function in this section. The name is FDP job program. It has only one parameter, but we don't use it right now. We will talk about it later. It's on how one line returns FDP job, which means we will drop every package we received on the interface. There are also some other kind of actions like FDP pass or FDP text, FDP reject. And the last line is the license section. This section is needed as some helper accessible only by GPL license the program. Okay. Now, let's see how to build the object. First of all, we need to install some dependencies like Clang LLAM, or LibBPF, LibXBP. Then we will build the object by our Clang with dash G. This will generate debug information. And we need to make the target as BPF. Source file as BP drop.C. Output is as BP drop.O. This is a ELF file. And we can also dump the object by LLAM object, OBG dump. As we have combined the object with dash G, it will... We can see the disassembled source code. It will return FDP drop. So, build with dash G is very useful for debug when we only have the object file but we don't have the source code. Also with LLAM OBG dumps, we can... With dash H, we can see the section lines like the FDP drop section, the license section, we just defined in the example. Okay. So, how to load the object? The easiest way to load the FDP object kernel is while the IP link. Before the test, there's one that don't load it on the default interface because our example will drop every packet come in the interface. So, if you load it on default interface, you may get Internet... You will disconnect with the Internet. Okay. First, we load it with IP link set VTH with model XDP Generic. There are also some other models like XDP driver or XDP offload, but it's only supported by a few drivers. If you want to test it, you can use XDP Generic which supports by all the drivers. And then supply the object and the section name. After load, it is with IP link show where you will show the lines. You can see the lines program XDP with ID1. We can also use DPF to program show to show the program we just load. Another tool is XDP loader. XDP loader status also shows the program we load. If you want to unload the object, just do IP link set interface with XDP Generic off. But we recommended to use XDP loader to load the XDP object because it's the only way it has to support it. And it's the only way we load the multi-programs on one interface. So let's see with XDP loader load with model XDP. XDP is the same with the example IP link that we use XDP Generic. And we also supply the section name, the interface name and the object file. So with XDP loader status, you can see we load the two XDP programs. The first is XDP dispatcher. It's provided by the XDP loader. The next one, XDP drop program, that is what we write before. Now with IP link show, you can see it only show the first program. But the BPF to program will show the two programs. First is XDP dispatcher. The second is XDP drop program. To load, to unload the program, just type XDP loader unloader. Dash A means R is the interface name. Okay. Okay, now we have learned how to write XDP program and load it to kernel. But this is just a hollow world program and the meaningless. So let's try a meaningful program. How about we drop some specific package, like a net filter or IP tables. We write a program to drop IPv6 package. First we need to see the parameter we just saw, the struct XDP-MD. There are two fields we will use today. The data and the data end. As we know, when the driver receives a package, the data starts from the Ethernet header. So the XDP-MD data point to the Ethernet header and the data end point to the end of the data. Now here is the full code. Now we need two more header lines to define the Ethernet header and the Ethernet header. Compared to the previous program, we add some. First we define the data end point to the CTX data end and the data point to CTX data. Then we define the Ethernet header variable ETH point to the data, which is the beginning of the data. Then we access the data in the Ethernet header. We must make sure we don't access invalid error. We need to check the data plus the size of the ETH header is greater than the data end. This check is compulsory by the BPF very far because we can't access and authorize the column memories. After that, we compare the protocol. If it's IPv6, we will drop it. If it's not, we will pass the package. It's very easy, right? If you want to drop some other kind of package like IPv4, or even TCP, UDP, or based on the source set, the port number, you can just do the same like this example and operate the package data based on the network format. You need to know the network format first. Now, is that all? No. What if we want to communicate with the kernel? What if we want to count the number we just dropped? Here, we will introduce a very important feature, the map. BPF maps are used to share data between the kernel and the user space. We can update the map data in kernel and read it from user space, or vice versa. Here is an example of the new BPF type format to define the maps. Here, we defined a structure, a struct RS count with the section maps. The struct type is the BPF map type per CPU array. It means we defined an array on each CPU on the system, and the K is unsigned as set to. The value is alone. There is only one entry in this struct. There are also some other kind of BPF maps like the hash array. These are defined in the Linux kernel. Okay, now let's see the full code. First, we define the map, and then we define a key. As we only have one entry, so the key is zero. When we get the IPv6 packet, we get the value from the map by BPF map lookup element. It means the map name and the key value. We get the value, and if there is a value, we plus one. Now we count the number in the kernel. But how do we get the value from user space? Okay, let's see. First, we build it with Zilang, and then we load it with the IPv6 loader, and then we receive some IPv6 packets. With the BPF2 map show, we will show all the maps we load. Let's see, the first map is per CPU array with name RSCount. This is just what we defined in the program. So with BPF map dump with ID16. And with K0, we can see on CPU0, the value is 13. With CPU1, the value is 7. And after you sum the value, you will get the total values we just dropped. Okay. So until now, after build the BPF object, we load it to kernel while XP loader. We saw the maps while BPF2. But what if we want to load the object and show the maps in theme2? And what if we want to define another output format? We don't use this as an output. So we need to write our own user space program to load the object and communicate with kernel to get the map data. Then we need to use libBPF and libXDB. For the detail, in this example is a very easy example. If you want to know the detailed usage, you can read it from the GitHub repo. Okay. So here is the example we use with libXDB and libBPF. First is header files. In the example, we use libBPFDev and libXDBDev. First, we define the following variables global, the interface index, and the FTP struct FTP program. And now let's see the main program. As the usage is program name plus the interface name. So first we get the interface theme and get the index of the interface. And then we load the FTP object by the libXDB program open file with the file name and the section name. We load the FTP program. Then we attach the FTP program to the interface with the FTP model SKD. Now we have loaded the program, but we want to get the map data. So we need to find the map ID from the BPF object. So first we need to find the BPF object from FTP object. Then we find the map fd from the BPF object with the map name rscount. After we get the map ID, we call a function named the push days to every two seconds to get the status. Now let's see what the push days looks like. In the push days, we will count the per CPU number and print out the total dropped package. So first we need to get the CPU numbers from the BPF number possible CPUs. And then we define a array called the values array with the max entry CPU number. Then we get the values from the map fd with k0 by BPF map lookup element. After that, we summary the values array two seconds. We also count the sum in total to get the total number. So at last we will print out the total package and the package per seconds. So before the testing, we need to set the set your limit to unlimited so we can get enough results. Then we build the XDP program, we build the program with GCC. Please note that the XDP program and the objects we showed at the beginning is not user space program. The XDP object is built at ELF file and will be loaded to kernel. While this program is run in user space and is used to load the XDP object and print out the map values. That's like the XDP loader or the BPF tools. That's why we build it with GCC. But the XDP object is built while clown. So now we build it with GCC and with Flags, L, BPF and L XDP. And we run the program with the interface name which one. And then after we receive some IPv6 package, it will print out the total dropped number and the package per second. So all the example code you want to be found in this link including this slide.