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.
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
15 For example, to install C-libmemif system-wide into the standard
18 $ git clone https://gerrit.fd.io/r/vpp
19 $ cd vpp/extras/libmemif
28 Package **libmemif** is not part of the **GoVPP** core and as such it is
29 not included in the [make build](../../Makefile) target.
30 Instead, it has its own target in the [top-level Makefile](../../Makefile)
31 used to build the attached examples with the adapter:
38 All **Go-libmemif** public APIs can be found in [adapter.go](adapter.go).
39 Please see the comments for a more detailed description.
40 Additionally, a list of all errors thrown by libmemif can be found
41 in [error.go](error.go).
45 **libmemif** needs to be first initialized with `Init(appName)`.
46 This has to be done only once in the context of the entire process.
47 Make sure to call `Cleanup()` to release all the resources allocated
48 by **libmemif** before exiting your application. Consider calling
49 `Init()` followed by `Cleanup()` scheduled with `defer` in the `main()`
52 Log messages are by default printed to stdout. Use `SetLogger()` to use
53 your own customized logger (can be changed before `Init()`).
55 Once **libmemif** is initialized, new memif interfaces can be created
56 with `CreateInterface(config, callbacks)`. See `MemifConfig` structure
57 definition to learn about possible memif configuration options.
58 If successful, `CreateInterface()` returns an instance of `Memif`
59 structure representing the underlying memif interface.
61 Callbacks are optional and can be shared across multiple memif instances.
62 Available callbacks are:
63 1. **OnConnect**: called when the connection is established.
64 By the time the callback is called, the Rx/Tx queues are initialized
65 and ready for data transmission. Interrupt channels are also
66 created and ready to be read from.
67 The user is expected to start polling for input packets via repeated
68 calls to `Memif.RxBurst(queueID, count)` or to initiate select
69 on the interrupt channels obtained with `Get*InterruptChan()`,
70 depending on the Rx mode. By default, all memif Rx queues are created
71 in the interrupt mode, but this can be changed per-queue with
72 `Memif.SetRxMode(queueID, mode)`.
73 2. **OnDisconnect**: called after the connection was closed. Immediately
74 after the user callback returns, Rx/Tx queues and interrupt channels
75 are also deallocated. The user defined callback should therefore ensure
76 that all the Rx/Tx operations are stopped before it returns.
78 **libmemif** was designed for a maximum possible performance. Packets
79 are sent and received in bulks, rather than one-by-one, using
80 `Memif.TxBurst(queueID, packets)` and `Memif.RxBurst(queueID, count)`,
81 respectively. Memif connection can consist of multiple queues in both
82 directions. A queue is one-directional wait-free ring buffer.
83 It is the unit of parallelism for data transmission. The maximum possible
84 lock-free granularity is therefore one go routine for one queue.
86 Interrupt channel for one specific Rx queue can be obtained with
87 `GetQueueInterruptChan(queueID)` as opposed to `GetInterruptChan()`
88 for all the Rx queues. There is only one interrupt signal sent for
89 an entire burst of packets, therefore an interrupt handling routine
90 should repeatedly call RxBurst() until an empty slice of packets
91 is returned. This way it is ensured that there are no packets left
92 on the queue unread when the interrupt signal is cleared.
93 Study the `ReadAndPrintPackets()` function in [raw-data example](examples/raw-data/raw-data.go).
95 For **libmemif** the packet is just an array of bytes. It does not care
96 what the actual content is. It is not required for a packet to follow
97 any network protocol in order to get transported from one end to another.
98 See the type declaration for `RawPacketData` and its use in `Memif.TxBurst()`
99 and `Memif.RxBurst()`.
101 In order to remove a memif interface, call `Memif.Close()`. If the memif
102 is in the connected state, the connection is first properly closed.
103 Do not touch memif after it was closed, let garbage collector to remove
104 the `Memif` instance. In the end, `Cleanup()` will also ensure that all
105 active memif interfaces are closed before the cleanup finalizes.
107 To use libmemif with `google/gopacket`, simply call `Memif.NewPacketHandle()`
108 to create `google/gopacket/PacketDataSource` from memif queue. After this you
109 can use gopacket API to read from `MemifPacketHandle` as normal. You can pass
110 optional `rxCount` when creating the packet handle and then when reading data,
111 handle will try to read more packets at once and cache them for next iteration.
112 Handle also includes convenience method `MemifPacketHandle.WritePacketData()`
113 that is simply calling 1 `Memif.TxBurst()` for provided data.
117 **Go-libmemif** ships with two simple examples demonstrating the usage
118 of the package with a detailed commentary.
119 The examples can be found in the subdirectory [examples](./examples).
121 #### Raw data (libmemif <-> libmemif)
123 *raw-data* is a basic example showing how to create a memif interface,
124 handle events through callbacks and perform Rx/Tx of raw data. Before
125 handling an actual packet it is important to understand the skeleton
126 of libmemif-based applications.
128 Since VPP expects proper packet data, it is not very useful to connect
129 *raw-data* example with VPP, even though it will work, since all
130 the received data will get dropped on the VPP side.
132 To create a connection of two raw-data instances, start two processes
133 concurrently in an arbitrary order:
136 $ cd extras/libmemif/examples/raw-data
141 $ cd extras/libmemif/examples/raw-data
145 Every 3 seconds both sides send 3 raw-data packets to the opposite end
146 through each of the 3 queues. The received packets are printed to stdout.
148 Stop an instance of *raw-data* with an interrupt signal (^C).
150 #### Jumbo Frames Raw data (libmemif <-> libmemif)
152 *jumbo-frames* is simple example how to send larger and larger jumbo
153 packets with libmemif adapter. This is simple copy of *raw-data* but with
154 sending larger packets, so for more information read its code and documentation.
158 *icmp-responder* is a simple example showing how to answer APR and ICMP
159 echo requests through a memif interface. Package `google/gopacket` is
160 used to decode and construct packets.
162 The appropriate VPP configuration for the opposite memif is:
164 vpp$ create memif socket id 1 filename /tmp/icmp-responder-example
165 vpp$ create interface memif id 1 socket-id 1 slave secret secret no-zero-copy
166 vpp$ set int state memif1/1 up
167 vpp$ set int ip address memif1/1 192.168.1.2/24
170 To start the example, simply type:
172 root$ ./icmp-responder
175 *icmp-responder* needs to be run as root so that it can access the socket
178 Normally, the memif interface is in the master mode. Pass CLI flag `--slave`
179 to create memif in the slave mode:
181 root$ ./icmp-responder --slave
184 Don't forget to put the opposite memif into the master mode in that case.
186 To verify the connection, run:
188 vpp$ ping 192.168.1.1
189 64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=.6974 ms
190 64 bytes from 192.168.1.1: icmp_seq=3 ttl=255 time=.6310 ms
191 64 bytes from 192.168.1.1: icmp_seq=4 ttl=255 time=1.0350 ms
192 64 bytes from 192.168.1.1: icmp_seq=5 ttl=255 time=.5359 ms
194 Statistics: 5 sent, 4 received, 20% packet loss
196 Time IP4 Flags Ethernet Interface
197 68.5648 192.168.1.1 D aa:aa:aa:aa:aa:aa memif0/1
199 *Note*: it is expected that the first ping is shown as lost.
200 It was actually converted to an ARP request. This is a VPP
201 specific feature common to all interface types.
203 Stop the example with an interrupt signal (^C).
205 #### GoPacket ICMP Responder
207 *gopacket* is a simple example showing how to answer APR and ICMP echo
208 requests through a memif interface. This example is mostly identical
209 to icmp-responder example, but it is using MemifPacketHandle API to
210 read and write packets using gopacket API.
212 The appropriate VPP configuration for the opposite memif is:
214 vpp$ create memif socket id 1 filename /tmp/gopacket-example
215 vpp$ create interface memif id 1 socket-id 1 slave secret secret no-zero-copy
216 vpp$ set int state memif1/1 up
217 vpp$ set int ip address memif1/1 192.168.1.2/24
220 To start the example, simply type:
225 gopacket needs to be run as root so that it can access the socket
228 Normally, the memif interface is in the master mode. Pass CLI flag "--slave"
229 to create memif in the slave mode:
231 root$ ./gopacket --slave
234 Don't forget to put the opposite memif into the master mode in that case.
236 To verify the connection, run:
238 vpp$ ping 192.168.1.1
239 64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=.6974 ms
240 64 bytes from 192.168.1.1: icmp_seq=3 ttl=255 time=.6310 ms
241 64 bytes from 192.168.1.1: icmp_seq=4 ttl=255 time=1.0350 ms
242 64 bytes from 192.168.1.1: icmp_seq=5 ttl=255 time=.5359 ms
244 Statistics: 5 sent, 4 received, 20% packet loss
246 Time IP4 Flags Ethernet Interface
247 68.5648 192.168.1.1 D aa:aa:aa:aa:aa:aa memif0/1
250 *Note*: it is expected that the first ping is shown as lost.
251 It was actually converted to an ARP request. This is a VPP
252 specific feature common to all interface types.
254 Stop the example with an interrupt signal (^C).