2 *------------------------------------------------------------------
3 * Copyright (c) 2020 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
26 const cookie = 0x3E31F20
28 // VersionMajor is memif protocols major version
29 const VersionMajor = 2
31 // VersionMinor is memif protocols minor version
32 const VersionMinor = 0
34 // Version is memif protocols version as uint16
35 // (M-Major m-minor: MMMMMMMMmmmmmmmm)
36 const Version = ((VersionMajor << 8) | VersionMinor)
41 msgTypeNone msgType = iota
52 type interfaceMode uint8
55 InterfaceModeEthernet interfaceMode = iota
57 InterfaceModePuntInject
63 const msgAddRingFlagS2M = (1 << 0)
67 // next buffer present
68 const descFlagNext = (1 << 0)
73 const ringFlagInterrupt = 1
75 func min16(a uint16, b uint16) uint16 {
82 func min8(a uint8, b uint8) uint8 {
89 type MsgHello struct {
100 type MsgInit struct {
109 type MsgAddRegion struct {
114 type MsgAddRing struct {
120 PrivateHdrSize uint16
123 type MsgConnect struct {
128 type MsgConnected struct {
133 type MsgDisconnect struct {
138 /* DESCRIPTOR BEGIN */
142 // desc field offsets
143 const descFlagsOffset = 0
144 const descRegionOffset = 2
145 const descLengthOffset = 4
146 const descOffsetOffset = 8
147 const descMetadataOffset = 12
149 // descBuf represents a memif descriptor as array of bytes
152 // newDescBuf returns new descriptor buffer
153 func newDescBuf() descBuf {
154 return make(descBuf, descSize)
157 // getDescBuff copies descriptor from shared memory to descBuf
158 func (q *Queue) getDescBuf(slot int, db descBuf) {
159 copy(db, q.i.regions[q.ring.region].data[q.ring.offset+ringSize+slot*descSize:])
162 // putDescBuf copies contents of descriptor buffer into shared memory
163 func (q *Queue) putDescBuf(slot int, db descBuf) {
164 copy(q.i.regions[q.ring.region].data[q.ring.offset+ringSize+slot*descSize:], db)
167 func (db descBuf) getFlags() int {
168 return (int)(binary.LittleEndian.Uint16((db)[descFlagsOffset:]))
171 func (db descBuf) getRegion() int {
172 return (int)(binary.LittleEndian.Uint16((db)[descRegionOffset:]))
175 func (db descBuf) getLength() int {
176 return (int)(binary.LittleEndian.Uint32((db)[descLengthOffset:]))
179 func (db descBuf) getOffset() int {
180 return (int)(binary.LittleEndian.Uint32((db)[descOffsetOffset:]))
183 func (db descBuf) getMetadata() int {
184 return (int)(binary.LittleEndian.Uint32((db)[descMetadataOffset:]))
187 func (db descBuf) setFlags(val int) {
188 binary.LittleEndian.PutUint16((db)[descFlagsOffset:], uint16(val))
191 func (db descBuf) setRegion(val int) {
192 binary.LittleEndian.PutUint16((db)[descRegionOffset:], uint16(val))
195 func (db descBuf) setLength(val int) {
196 binary.LittleEndian.PutUint32((db)[descLengthOffset:], uint32(val))
199 func (db descBuf) setOffset(val int) {
200 binary.LittleEndian.PutUint32((db)[descOffsetOffset:], uint32(val))
203 func (db descBuf) setMetadata(val int) {
204 binary.LittleEndian.PutUint32((db)[descMetadataOffset:], uint32(val))
214 ringTypeS2M ringType = iota
220 // ring field offsets
221 const ringCookieOffset = 0
222 const ringFlagsOffset = 4
223 const ringHeadOffset = 6
224 const ringTailOffset = 64
226 // ringBuf represents a memif ring as array of bytes
238 // newRing returns new memif ring based on data received in msgAddRing (master only)
239 func newRing(regionIndex int, ringType ringType, ringOffset int, log2RingSize int) *ring {
242 size: (1 << log2RingSize),
243 log2Size: log2RingSize,
244 rb: make(ringBuf, ringSize),
251 // newRing returns a new memif ring
252 func (i *Interface) newRing(regionIndex int, ringType ringType, ringIndex int) *ring {
255 size: (1 << i.run.Log2RingSize),
256 log2Size: int(i.run.Log2RingSize),
257 rb: make(ringBuf, ringSize),
260 rSize := ringSize + descSize*r.size
261 if r.ringType == ringTypeS2M {
264 r.offset = int(i.run.NumQueuePairs) * rSize
266 r.offset += ringIndex * rSize
271 // putRing put the ring to the shared memory
272 func (q *Queue) putRing() {
273 copy(q.i.regions[q.ring.region].data[q.ring.offset:], q.ring.rb)
276 // updateRing updates ring with data from shared memory
277 func (q *Queue) updateRing() {
278 copy(q.ring.rb, q.i.regions[q.ring.region].data[q.ring.offset:])
281 func (r *ring) getCookie() int {
282 return (int)(binary.LittleEndian.Uint32((r.rb)[ringCookieOffset:]))
285 // getFlags returns the flags value from ring buffer
286 // Use Queue.getFlags in fast-path to avoid updating the whole ring.
287 func (r *ring) getFlags() int {
288 return (int)(binary.LittleEndian.Uint16((r.rb)[ringFlagsOffset:]))
291 // getHead returns the head pointer value from ring buffer.
292 // Use readHead in fast-path to avoid updating the whole ring.
293 func (r *ring) getHead() int {
294 return (int)(binary.LittleEndian.Uint16((r.rb)[ringHeadOffset:]))
297 // getTail returns the tail pointer value from ring buffer.
298 // Use readTail in fast-path to avoid updating the whole ring.
299 func (r *ring) getTail() int {
300 return (int)(binary.LittleEndian.Uint16((r.rb)[ringTailOffset:]))
303 func (r *ring) setCookie(val int) {
304 binary.LittleEndian.PutUint32((r.rb)[ringCookieOffset:], uint32(val))
307 func (r *ring) setFlags(val int) {
308 binary.LittleEndian.PutUint16((r.rb)[ringFlagsOffset:], uint16(val))
311 // setHead set the head pointer value int the ring buffer.
312 // Use writeHead in fast-path to avoid putting the whole ring into shared memory.
313 func (r *ring) setHead(val int) {
314 binary.LittleEndian.PutUint16((r.rb)[ringHeadOffset:], uint16(val))
317 // setTail set the tail pointer value int the ring buffer.
318 // Use writeTail in fast-path to avoid putting the whole ring into shared memory.
319 func (r *ring) setTail(val int) {
320 binary.LittleEndian.PutUint16((r.rb)[ringTailOffset:], uint16(val))
325 // isInterrupt returns true if the queue is in interrupt mode
326 func (q *Queue) isInterrupt() bool {
327 return (q.getFlags() & ringFlagInterrupt) == 0
330 // interrupt performs an interrupt if the queue is in interrupt mode
331 func (q *Queue) interrupt() error {
333 buf := make([]byte, 8)
334 binary.PutUvarint(buf, 1)
335 n, err := syscall.Write(q.interruptFd, buf[:])
340 return fmt.Errorf("Faild to write to eventfd")