1bc943f9e2a581ecebab4a4ab5356cfb3022229a
[govpp.git] / extras / libmemif / examples / jumbo-frames / jumbo-frames.go
1 // jumbo-frames is simple example how to send larger and larger jumbo packets with libmemif adapter. This is simple copy
2 // of raw-data but with sending larger packets, so for more information read its code and docs.
3 package main
4
5 import (
6         "fmt"
7         "os"
8         "os/signal"
9         "sync"
10         "time"
11
12         "git.fd.io/govpp.git/extras/libmemif"
13 )
14
15 const (
16         Socket             = "/tmp/jumbo-frames-example"
17         Secret             = "secret"
18         ConnectionID       = 1
19         NumQueues    uint8 = 3
20 )
21
22 var wg sync.WaitGroup
23 var stopCh chan struct{}
24
25 func OnConnect(memif *libmemif.Memif) (err error) {
26         details, err := memif.GetDetails()
27         if err != nil {
28                 fmt.Printf("libmemif.GetDetails() error: %v\n", err)
29         }
30         fmt.Printf("memif %s has been connected: %+v\n", memif.IfName, details)
31
32         stopCh = make(chan struct{})
33         var i uint8
34         for i = 0; i < uint8(len(details.RxQueues)); i++ {
35                 wg.Add(1)
36                 go ReadAndPrintPackets(memif, i)
37         }
38         for i = 0; i < uint8(len(details.TxQueues)); i++ {
39                 wg.Add(1)
40                 go SendPackets(memif, i)
41         }
42         return nil
43 }
44
45 func OnDisconnect(memif *libmemif.Memif) (err error) {
46         fmt.Printf("memif %s has been disconnected\n", memif.IfName)
47         close(stopCh)
48         wg.Wait()
49         return nil
50 }
51
52 func ReadAndPrintPackets(memif *libmemif.Memif, queueID uint8) {
53         defer wg.Done()
54
55         interruptCh, err := memif.GetQueueInterruptChan(queueID)
56         if err != nil {
57                 switch err {
58                 case libmemif.ErrQueueID:
59                         fmt.Printf("libmemif.Memif.GetQueueInterruptChan() complains about invalid queue id!?")
60                 default:
61                         fmt.Printf("libmemif.Memif.GetQueueInterruptChan() error: %v\n", err)
62                 }
63                 return
64         }
65
66         counter := 0
67         for {
68                 select {
69                 case <-interruptCh:
70                         counter++
71                         for {
72                                 packets, err := memif.RxBurst(queueID, 10)
73                                 if err != nil {
74                                         fmt.Printf("libmemif.Memif.RxBurst() error: %v\n", err)
75                                 } else {
76                                         if len(packets) == 0 {
77                                                 break
78                                         }
79                                         for _, packet := range packets {
80                                                 fmt.Printf("Received packet queue=%d: %v in burst %d\n", queueID, len(packet), counter)
81                                         }
82                                 }
83                         }
84                 case <-stopCh:
85                         return
86                 }
87         }
88 }
89
90 func SendPackets(memif *libmemif.Memif, queueID uint8) {
91         defer wg.Done()
92
93         counter := 0
94         for {
95                 select {
96                 case <-time.After(3 * time.Second):
97                         counter++
98                         packetMul :=  counter % 100 + 1 // Limit max iterations to 100 to not go out of bounds
99                         packets := []libmemif.RawPacketData{
100                                 make([]byte, 128*packetMul),
101                                 make([]byte, 256*packetMul),
102                                 make([]byte, 512*packetMul),
103                         }
104                         sent := 0
105                         for {
106                                 count, err := memif.TxBurst(queueID, packets[sent:])
107                                 if err != nil {
108                                         fmt.Printf("libmemif.Memif.TxBurst() error: %v\n", err)
109                                         break
110                                 } else {
111                                         fmt.Printf("libmemif.Memif.TxBurst() has sent %d packets in burst %v.\n", count, counter)
112                                         sent += int(count)
113                                         if sent == len(packets) {
114                                                 break
115                                         }
116                                 }
117                         }
118                 case <-stopCh:
119                         return
120                 }
121         }
122 }
123
124 func main() {
125         var isMaster = true
126         var appSuffix string
127         if len(os.Args) > 1 && (os.Args[1] == "--slave" || os.Args[1] == "-slave") {
128                 isMaster = false
129                 appSuffix = "-slave"
130         }
131
132         appName := "jumbo-frames" + appSuffix
133         fmt.Println("Initializing libmemif as ", appName)
134         err := libmemif.Init(appName)
135         if err != nil {
136                 fmt.Printf("libmemif.Init() error: %v\n", err)
137                 return
138         }
139         defer libmemif.Cleanup()
140
141         memifCallbacks := &libmemif.MemifCallbacks{
142                 OnConnect:    OnConnect,
143                 OnDisconnect: OnDisconnect,
144         }
145
146         memifConfig := &libmemif.MemifConfig{
147                 MemifMeta: libmemif.MemifMeta{
148                         IfName:         "memif1",
149                         ConnID:         ConnectionID,
150                         SocketFilename: Socket,
151                         Secret:         Secret,
152                         IsMaster:       isMaster,
153                         Mode:           libmemif.IfModeEthernet,
154                 },
155                 MemifShmSpecs: libmemif.MemifShmSpecs{
156                         NumRxQueues:  NumQueues,
157                         NumTxQueues:  NumQueues,
158                         BufferSize:   2048,
159                         Log2RingSize: 10,
160                 },
161         }
162
163         fmt.Printf("Callbacks: %+v\n", memifCallbacks)
164         fmt.Printf("Config: %+v\n", memifConfig)
165
166         memif, err := libmemif.CreateInterface(memifConfig, memifCallbacks)
167         if err != nil {
168                 fmt.Printf("libmemif.CreateInterface() error: %v\n", err)
169                 return
170         }
171         defer memif.Close()
172
173         sigChan := make(chan os.Signal, 1)
174         signal.Notify(sigChan, os.Interrupt)
175         <-sigChan
176 }