39a6d584fa2fbd93f2591c02eff55be3800a53bf
[govpp.git] / extras / libmemif / README.md
1 ## Go-libmemif
2
3 Package **libmemif** is a Golang adapter for the **libmemif library**
4 (`extras/libmemif` in the [VPP](https://wiki.fd.io/view/VPP) repository).
5 To differentiate between the adapter and the underlying C-written library,
6 labels `Go-libmemif` and `C-libmemif` are used in the documentation.
7
8 ### Requirements
9
10 libmemif for Golang is build on the top of the original, C-written
11 libmemif library using `cgo`. It is therefore necessary to have C-libmemif
12 header files and the library itself installed in locations known
13 to the compiler.
14
15 For example, to install C-libmemif system-wide into the standard
16 locations, execute:
17 ```
18 $ git clone https://gerrit.fd.io/r/vpp
19 $ cd vpp/extras/libmemif
20 $ make install
21 ```
22
23 ### Build
24
25 Package **libmemif** is not part of the **GoVPP** core and as such it is
26 not included in the [make build](../../Makefile) target.
27 Instead, it has its own target in the [top-level Makefile](../../Makefile)
28 used to build the attached examples with the adapter:
29 ```
30 $ make extras
31 ```
32
33 ### APIs
34
35 All **Go-libmemif** public APIs can be found in [adapter.go](adapter.go).
36 Please see the comments for a more detailed description.
37 Additionally, a list of all errors thrown by libmemif can be found
38 in [error.go](error.go).
39
40 ### Usage
41
42 **libmemif** needs to be first initialized with `Init(appName)`.
43 This has to be done only once in the context of the entire process.
44 Make sure to call `Cleanup()` to release all the resources allocated
45 by **libmemif** before exiting your application. Consider calling
46 `Init()` followed by `Cleanup()` scheduled with `defer` in the `main()`
47 function.
48
49 Log messages are by default printed to stdout. Use `SetLogger()` to use
50 your own customized logger (can be changed before `Init()`).
51
52 Once **libmemif** is initialized, new memif interfaces can be created
53 with `CreateInterface(config, callbacks)`. See `MemifConfig` structure
54 definition to learn about possible memif configuration options.
55 If successful, `CreateInterface()` returns an instance of `Memif`
56 structure representing the underlying memif interface.
57
58 Callbacks are optional and can be shared across multiple memif instances.
59 Available callbacks are:
60 1. **OnConnect**: called when the connection is established.
61    By the time the callback is called, the Rx/Tx queues are initialized
62    and ready for data transmission. Interrupt channels are also
63    created and ready to be read from.
64    The user is expected to start polling for input packets via repeated
65    calls to `Memif.RxBurst(queueID, count)` or to initiate select
66    on the interrupt channels obtained with `Get*InterruptChan()`,
67    depending on the Rx mode. By default, all memif Rx queues are created
68    in the interrupt mode, but this can be changed per-queue with
69    `Memif.SetRxMode(queueID, mode)`.
70 2. **OnDisconnect**: called after the connection was closed. Immediately
71    after the user callback returns, Rx/Tx queues and interrupt channels
72    are also deallocated. The user defined callback should therefore ensure
73    that all the Rx/Tx operations are stopped before it returns.
74
75 **libmemif** was designed for a maximum possible performance. Packets
76 are sent and received in bulks, rather than one-by-one, using
77 `Memif.TxBurst(queueID, packets)` and `Memif.RxBurst(queueID, count)`,
78 respectively. Memif connection can consists of multiple queues in both
79 directions. A queue is one-directional wait-free ring buffer.
80 It is the unit of parallelism for data transmission. The maximum possible
81 lock-free granularity is therefore one go routine for one queue.
82
83 Interrupt channel for one specific Rx queue can be obtained with
84 `GetQueueInterruptChan(queueID)` as opposed to `GetInterruptChan()`
85 for all the Rx queues. There is only one interrupt signal sent for
86 an entire burst of packets, therefore an interrupt handling routine
87 should repeatedly call RxBurst() until an empty slice of packets
88 is returned. This way it is ensured that there are no packets left
89 on the queue unread when the interrupt signal is cleared.
90 Study the `ReadAndPrintPackets()` function in [raw-data example](examples/raw-data/raw-data.go).
91
92 For **libmemif** the packet is just an array of bytes. It does not care
93 what the actual content is. It is not required for a packet to follow
94 any network protocol in order to get transported from one end to another.
95 See the type declaration for `RawPacketData` and its use in `Memif.TxBurst()`
96 and `Memif.RxBurst()`.
97
98 In order to remove a memif interface, call `Memif.Close()`. If the memif
99 is in the connected state, the connection is first properly closed.
100 Do not touch memif after it was closed, let garbage collector to remove
101 the `Memif` instance. In the end, `Cleanup()` will also ensure that all
102 active memif interfaces are closed before the cleanup finalizes.
103
104 ### Examples
105
106 **Go-libmemif** ships with two simple examples demonstrating the usage
107 of the package with a detailed commentary.
108 The examples can be found in the subdirectory [examples](./examples).
109
110 #### Raw data (libmemif <-> libmemif)
111
112 *raw-data* is a basic example showing how to create a memif interface,
113 handle events through callbacks and perform Rx/Tx of raw data. Before
114 handling an actual packets it is important to understand the skeleton
115 of libmemif-based applications.
116
117 Since VPP expects proper packet data, it is not very useful to connect
118 *raw-data* example with VPP, even though it will work, since all
119 the received data will get dropped on the VPP side.
120
121 To create a connection of two raw-data instances, start two processes
122 concurrently in an arbitrary order:
123  - *master* memif:
124    ```
125    $ cd extras/libmemif/examples/raw-data
126    $ ./raw-data
127    ```
128  - *slave* memif:
129    ```
130    $ cd extras/libmemif/examples/raw-data
131    $ ./raw-data --slave
132    ```
133
134 Every 3 seconds both sides send 3 raw-data packets to the opposite end
135 through each of the 3 queues. The received packets are printed to stdout.
136
137 Stop an instance of *raw-data* with an interrupt signal (^C).
138
139 #### ICMP Responder
140
141 *icmp-responder* is a simple example showing how to answer APR and ICMP
142 echo requests through a memif interface. Package `google/gopacket` is
143 used to decode and construct packets.
144
145 The appropriate VPP configuration for the opposite memif is:
146 ```
147 vpp$ create memif id 1 socket /tmp/icmp-responder-example slave secret secret
148 vpp$ set int state memif0/1 up
149 vpp$ set int ip address memif0/1 192.168.1.2/24
150 ```
151
152 To start the example, simply type:
153 ```
154 root$ ./icmp-responder
155 ```
156
157 *icmp-responder* needs to be run as root so that it can access the socket
158 created by VPP.
159
160 Normally, the memif interface is in the master mode. Pass CLI flag `--slave`
161 to create memif in the slave mode:
162 ```
163 root$ ./icmp-responder --slave
164 ```
165
166 Don't forget to put the opposite memif into the master mode in that case.
167
168 To verify the connection, run:
169 ```
170 vpp$ ping 192.168.1.1
171 64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=.6974 ms
172 64 bytes from 192.168.1.1: icmp_seq=3 ttl=255 time=.6310 ms
173 64 bytes from 192.168.1.1: icmp_seq=4 ttl=255 time=1.0350 ms
174 64 bytes from 192.168.1.1: icmp_seq=5 ttl=255 time=.5359 ms
175
176 Statistics: 5 sent, 4 received, 20% packet loss
177 vpp$ sh ip arp
178     Time           IP4       Flags      Ethernet              Interface
179     68.5648   192.168.1.1     D    aa:aa:aa:aa:aa:aa memif0/1
180 ```
181 *Note*: it is expected that the first ping is shown as lost.
182         It was actually converted to an ARP request. This is a VPP
183         specific feature common to all interface types.
184
185 Stop the example with an interrupt signal (^C).