Skip to content

Commit b098bb1

Browse files
authored
AK-46144 use an interface to handle packet burst (#3)
+ accept an interface for NewPacketHandle makes it easy to unit tests functions which use NewPacketHandle without interacting with the lower level memif structure. + used in alkiranet/csn/services/memif-receiver service
1 parent c6a3e43 commit b098bb1

File tree

3 files changed

+77
-52
lines changed

3 files changed

+77
-52
lines changed

extras/libmemif/README.md

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ to the compiler.
1414

1515
For example, to install C-libmemif system-wide into the standard
1616
locations, execute:
17+
1718
```
1819
$ git clone https://gerrit.fd.io/r/vpp
1920
$ cd vpp/extras/libmemif
@@ -28,6 +29,7 @@ Package **libmemif** is not part of the **GoVPP** core and as such it is
2829
not included in the [make build](../../Makefile) target.
2930
Instead, it has its own target in the [top-level Makefile](../../Makefile)
3031
used to build the attached examples with the adapter:
32+
3133
```
3234
$ make extras
3335
```
@@ -59,6 +61,7 @@ structure representing the underlying memif interface.
5961

6062
Callbacks are optional and can be shared across multiple memif instances.
6163
Available callbacks are:
64+
6265
1. **OnConnect**: called when the connection is established.
6366
By the time the callback is called, the Rx/Tx queues are initialized
6467
and ready for data transmission. Interrupt channels are also
@@ -103,7 +106,7 @@ Do not touch memif after it was closed, let garbage collector to remove
103106
the `Memif` instance. In the end, `Cleanup()` will also ensure that all
104107
active memif interfaces are closed before the cleanup finalizes.
105108

106-
To use libmemif with `google/gopacket`, simply call `Memif.NewPacketHandle()`
109+
To use libmemif with `google/gopacket`, simply call `libmemif.NewPacketHandle()`
107110
to create `google/gopacket/PacketDataSource` from memif queue. After this you
108111
can use gopacket API to read from `MemifPacketHandle` as normal. You can pass
109112
optional `rxCount` when creating the packet handle and then when reading data,
@@ -119,46 +122,48 @@ The examples can be found in the subdirectory [examples](./examples).
119122

120123
#### Raw data (libmemif <-> libmemif)
121124

122-
*raw-data* is a basic example showing how to create a memif interface,
125+
_raw-data_ is a basic example showing how to create a memif interface,
123126
handle events through callbacks and perform Rx/Tx of raw data. Before
124127
handling an actual packets it is important to understand the skeleton
125128
of libmemif-based applications.
126129

127130
Since VPP expects proper packet data, it is not very useful to connect
128-
*raw-data* example with VPP, even though it will work, since all
131+
_raw-data_ example with VPP, even though it will work, since all
129132
the received data will get dropped on the VPP side.
130133

131134
To create a connection of two raw-data instances, start two processes
132135
concurrently in an arbitrary order:
133-
- *master* memif:
134-
```
135-
$ cd extras/libmemif/examples/raw-data
136-
$ ./raw-data
137-
```
138-
- *slave* memif:
139-
```
140-
$ cd extras/libmemif/examples/raw-data
141-
$ ./raw-data --slave
142-
```
136+
137+
- _master_ memif:
138+
```
139+
$ cd extras/libmemif/examples/raw-data
140+
$ ./raw-data
141+
```
142+
- _slave_ memif:
143+
```
144+
$ cd extras/libmemif/examples/raw-data
145+
$ ./raw-data --slave
146+
```
143147

144148
Every 3 seconds both sides send 3 raw-data packets to the opposite end
145149
through each of the 3 queues. The received packets are printed to stdout.
146150

147-
Stop an instance of *raw-data* with an interrupt signal (^C).
151+
Stop an instance of _raw-data_ with an interrupt signal (^C).
148152

149153
#### Jumbo Frames Raw data (libmemif <-> libmemif)
150154

151-
*jumbo-frames* is simple example how to send larger and larger jumbo
152-
packets with libmemif adapter. This is simple copy of *raw-data* but with
155+
_jumbo-frames_ is simple example how to send larger and larger jumbo
156+
packets with libmemif adapter. This is simple copy of _raw-data_ but with
153157
sending larger packets, so for more information read its code and documentation.
154158

155159
#### ICMP Responder
156160

157-
*icmp-responder* is a simple example showing how to answer APR and ICMP
161+
_icmp-responder_ is a simple example showing how to answer APR and ICMP
158162
echo requests through a memif interface. Package `google/gopacket` is
159163
used to decode and construct packets.
160164

161165
The appropriate VPP configuration for the opposite memif is:
166+
162167
```
163168
vpp$ create memif socket id 1 filename /tmp/icmp-responder-example
164169
vpp$ create interface memif id 1 socket-id 1 slave secret secret no-zero-copy
@@ -167,22 +172,25 @@ vpp$ set int ip address memif1/1 192.168.1.2/24
167172
```
168173

169174
To start the example, simply type:
175+
170176
```
171177
root$ ./icmp-responder
172178
```
173179

174-
*icmp-responder* needs to be run as root so that it can access the socket
180+
_icmp-responder_ needs to be run as root so that it can access the socket
175181
created by VPP.
176182

177183
Normally, the memif interface is in the master mode. Pass CLI flag `--slave`
178184
to create memif in the slave mode:
185+
179186
```
180187
root$ ./icmp-responder --slave
181188
```
182189

183190
Don't forget to put the opposite memif into the master mode in that case.
184191

185192
To verify the connection, run:
193+
186194
```
187195
vpp$ ping 192.168.1.1
188196
64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=.6974 ms
@@ -195,20 +203,22 @@ vpp$ sh ip arp
195203
Time IP4 Flags Ethernet Interface
196204
68.5648 192.168.1.1 D aa:aa:aa:aa:aa:aa memif0/1
197205
```
198-
*Note*: it is expected that the first ping is shown as lost.
199-
It was actually converted to an ARP request. This is a VPP
200-
specific feature common to all interface types.
206+
207+
_Note_: it is expected that the first ping is shown as lost.
208+
It was actually converted to an ARP request. This is a VPP
209+
specific feature common to all interface types.
201210

202211
Stop the example with an interrupt signal (^C).
203212

204213
#### GoPacket ICMP Responder
205214

206-
*gopacket* is a simple example showing how to answer APR and ICMP echo
215+
_gopacket_ is a simple example showing how to answer APR and ICMP echo
207216
requests through a memif interface. This example is mostly identical
208217
to icmp-responder example, but it is using MemifPacketHandle API to
209218
read and write packets using gopacket API.
210219

211220
The appropriate VPP configuration for the opposite memif is:
221+
212222
```
213223
vpp$ create memif socket id 1 filename /tmp/gopacket-example
214224
vpp$ create interface memif id 1 socket-id 1 slave secret secret no-zero-copy
@@ -217,6 +227,7 @@ vpp$ set int ip address memif1/1 192.168.1.2/24
217227
```
218228

219229
To start the example, simply type:
230+
220231
```
221232
root$ ./gopacket
222233
```
@@ -226,13 +237,15 @@ created by VPP.
226237

227238
Normally, the memif interface is in the master mode. Pass CLI flag "--slave"
228239
to create memif in the slave mode:
240+
229241
```
230242
root$ ./gopacket --slave
231243
```
232244

233245
Don't forget to put the opposite memif into the master mode in that case.
234246

235247
To verify the connection, run:
248+
236249
```
237250
vpp$ ping 192.168.1.1
238251
64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=.6974 ms
@@ -246,8 +259,8 @@ Time IP4 Flags Ethernet Interface
246259
68.5648 192.168.1.1 D aa:aa:aa:aa:aa:aa memif0/1
247260
```
248261

249-
*Note*: it is expected that the first ping is shown as lost.
250-
It was actually converted to an ARP request. This is a VPP
251-
specific feature common to all interface types.
262+
_Note_: it is expected that the first ping is shown as lost.
263+
It was actually converted to an ARP request. This is a VPP
264+
specific feature common to all interface types.
252265

253266
Stop the example with an interrupt signal (^C).

extras/libmemif/examples/gopacket/gopacket.go

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,38 @@
44
// read and write packets using gopacket API.
55
//
66
// The appropriate VPP configuration for the opposite memif is:
7-
// vpp$ create memif socket id 1 filename /tmp/gopacket-example
8-
// vpp$ create interface memif id 1 socket-id 1 slave secret secret no-zero-copy
9-
// vpp$ set int state memif1/1 up
10-
// vpp$ set int ip address memif1/1 192.168.1.2/24
7+
//
8+
// vpp$ create memif socket id 1 filename /tmp/gopacket-example
9+
// vpp$ create interface memif id 1 socket-id 1 slave secret secret no-zero-copy
10+
// vpp$ set int state memif1/1 up
11+
// vpp$ set int ip address memif1/1 192.168.1.2/24
1112
//
1213
// To start the example, simply type:
13-
// root$ ./gopacket
14+
//
15+
// root$ ./gopacket
1416
//
1517
// gopacket needs to be run as root so that it can access the socket
1618
// created by VPP.
1719
//
1820
// Normally, the memif interface is in the master mode. Pass CLI flag "--slave"
1921
// to create memif in the slave mode:
20-
// root$ ./gopacket --slave
22+
//
23+
// root$ ./gopacket --slave
2124
//
2225
// Don't forget to put the opposite memif into the master mode in that case.
2326
//
2427
// To verify the connection, run:
25-
// vpp$ ping 192.168.1.1
26-
// 64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=.6974 ms
27-
// 64 bytes from 192.168.1.1: icmp_seq=3 ttl=255 time=.6310 ms
28-
// 64 bytes from 192.168.1.1: icmp_seq=4 ttl=255 time=1.0350 ms
29-
// 64 bytes from 192.168.1.1: icmp_seq=5 ttl=255 time=.5359 ms
3028
//
31-
// Statistics: 5 sent, 4 received, 20% packet loss
32-
// vpp$ sh ip arp
33-
// Time IP4 Flags Ethernet Interface
34-
// 68.5648 192.168.1.1 D aa:aa:aa:aa:aa:aa memif0/1
29+
// vpp$ ping 192.168.1.1
30+
// 64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=.6974 ms
31+
// 64 bytes from 192.168.1.1: icmp_seq=3 ttl=255 time=.6310 ms
32+
// 64 bytes from 192.168.1.1: icmp_seq=4 ttl=255 time=1.0350 ms
33+
// 64 bytes from 192.168.1.1: icmp_seq=5 ttl=255 time=.5359 ms
34+
//
35+
// Statistics: 5 sent, 4 received, 20% packet loss
36+
// vpp$ sh ip arp
37+
// Time IP4 Flags Ethernet Interface
38+
// 68.5648 192.168.1.1 D aa:aa:aa:aa:aa:aa memif0/1
3539
//
3640
// Note: it is expected that the first ping is shown as lost. It was actually
3741
// converted to an ARP request. This is a VPP feature common to all interface
@@ -43,13 +47,14 @@ package main
4347
import (
4448
"errors"
4549
"fmt"
46-
"github.com/alkiranet/govpp/extras/libmemif"
47-
"github.com/google/gopacket"
48-
"github.com/google/gopacket/layers"
4950
"io"
5051
"net"
5152
"os"
5253
"os/signal"
54+
55+
"github.com/alkiranet/govpp/extras/libmemif"
56+
"github.com/google/gopacket"
57+
"github.com/google/gopacket/layers"
5358
)
5459

5560
var (
@@ -89,7 +94,7 @@ func OnConnect(memif *libmemif.Memif) (err error) {
8994
continue
9095
}
9196

92-
go CreateInterruptCallback(memif.NewPacketHandle(queue.QueueID, 10), ch, OnInterrupt)
97+
go CreateInterruptCallback(libmemif.NewPacketHandle(memif, queue.QueueID, 10), ch, OnInterrupt)
9398
}
9499

95100
return

extras/libmemif/packethandle.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,26 @@
1515
package libmemif
1616

1717
import (
18-
"github.com/google/gopacket"
19-
"time"
20-
"sync"
2118
"io"
19+
"sync"
20+
"time"
21+
22+
"github.com/google/gopacket"
2223
)
2324

2425
type memoizedPacket struct {
2526
data RawPacketData
2627
ci gopacket.CaptureInfo
2728
}
2829

30+
// BurstHandler is an interface that implements methods for reading and writing packets in bursts.
31+
type BurstHandler interface {
32+
RxBurst(queueID uint8, count uint16) (packets []RawPacketData, err error)
33+
TxBurst(queueID uint8, packets []RawPacketData) (count uint16, err error)
34+
}
35+
2936
type MemifPacketHandle struct {
30-
memif *Memif
37+
handler BurstHandler
3138
queueId uint8
3239
rxCount uint16
3340

@@ -43,13 +50,13 @@ type MemifPacketHandle struct {
4350

4451
// Create new GoPacket packet handle from libmemif queue. rxCount determines how many packets will be read
4552
// at once, minimum value is 1
46-
func (memif *Memif) NewPacketHandle(queueId uint8, rxCount uint16) *MemifPacketHandle {
53+
func NewPacketHandle(burstHandler BurstHandler, queueId uint8, rxCount uint16) *MemifPacketHandle {
4754
if rxCount == 0 {
4855
rxCount = 1
4956
}
5057

5158
return &MemifPacketHandle{
52-
memif: memif,
59+
handler: burstHandler,
5360
queueId: queueId,
5461
rxCount: rxCount,
5562
}
@@ -70,7 +77,7 @@ func (handle *MemifPacketHandle) ReadPacketData() (data []byte, ci gopacket.Capt
7077
queueLen := len(handle.packetQueue)
7178

7279
if queueLen == 0 {
73-
packets, burstErr := handle.memif.RxBurst(handle.queueId, handle.rxCount)
80+
packets, burstErr := handle.handler.RxBurst(handle.queueId, handle.rxCount)
7481
packetsLen := len(packets)
7582

7683
if burstErr != nil {
@@ -118,7 +125,7 @@ func (handle *MemifPacketHandle) WritePacketData(data []byte) (err error) {
118125
return
119126
}
120127

121-
count, err := handle.memif.TxBurst(handle.queueId, []RawPacketData{data})
128+
count, err := handle.handler.TxBurst(handle.queueId, []RawPacketData{data})
122129

123130
if err != nil {
124131
return

0 commit comments

Comments
 (0)