aboutsummaryrefslogtreecommitdiffstats
path: root/bootstrap-verify-perf-ligato.sh
AgeCommit message (Expand)AuthorFilesLines
2018-01-02CSIT-870 Kubernetes/Ligato integrationPeter Mikus1-5/+4
2017-10-20Rename all container based test following name conventionsPeter Mikus1-23/+23
2017-10-16CSIT-841 Optimize creating of vnf-agent docker image Part IPeter Mikus1-11/+71
2017-10-12CSIT-748 vnf-agent integrationPeter Mikus1-0/+363
326' href='#n326'>326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
/*
 *------------------------------------------------------------------
 * Copyright (c) 2020 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *------------------------------------------------------------------
 */

package memif

import (
	"encoding/binary"
	"fmt"
	"syscall"
)

const cookie = 0x3E31F20

// VersionMajor is memif protocols major version
const VersionMajor = 2

// VersionMinor is memif protocols minor version
const VersionMinor = 0

// Version is memif protocols version as uint16
// (M-Major m-minor: MMMMMMMMmmmmmmmm)
const Version = ((VersionMajor << 8) | VersionMinor)

type msgType uint16

const (
	msgTypeNone msgType = iota
	msgTypeAck
	msgTypeHello
	msgTypeInit
	msgTypeAddRegion
	msgTypeAddRing
	msgTypeConnect
	msgTypeConnected
	msgTypeDisconnect
)

type interfaceMode uint8

const (
	InterfaceModeEthernet interfaceMode = iota
	InterfaceModeIp
	InterfaceModePuntInject
)

const msgSize = 128
const msgTypeSize = 2

const msgAddRingFlagS2M = (1 << 0)

// Descriptor flags
//
// next buffer present
const descFlagNext = (1 << 0)

// Ring flags
//
// Interrupt
const ringFlagInterrupt = 1

func min16(a uint16, b uint16) uint16 {
	if a < b {
		return a
	}
	return b
}

func min8(a uint8, b uint8) uint8 {
	if a < b {
		return a
	}
	return b
}

type MsgHello struct {
	// app name
	Name            [32]byte
	VersionMin      uint16
	VersionMax      uint16
	MaxRegion       uint16
	MaxRingM2S      uint16
	MaxRingS2M      uint16
	MaxLog2RingSize uint8
}

type MsgInit struct {
	Version uint16
	Id      uint32
	Mode    interfaceMode
	Secret  [24]byte
	// app name
	Name [32]byte
}

type MsgAddRegion struct {
	Index uint16
	Size  uint64
}

type MsgAddRing struct {
	Flags          uint16
	Index          uint16
	Region         uint16
	Offset         uint32
	RingSizeLog2   uint8
	PrivateHdrSize uint16
}

type MsgConnect struct {
	// interface name
	Name [32]byte
}

type MsgConnected struct {
	// interface name
	Name [32]byte
}

type MsgDisconnect struct {
	Code   uint32
	String [96]byte
}

/* DESCRIPTOR BEGIN */

const descSize = 16

// desc field offsets
const descFlagsOffset = 0
const descRegionOffset = 2
const descLengthOffset = 4
const descOffsetOffset = 8
const descMetadataOffset = 12

// descBuf represents a memif descriptor as array of bytes
type descBuf []byte

// newDescBuf returns new descriptor buffer
func newDescBuf() descBuf {
	return make(descBuf, descSize)
}

// getDescBuff copies descriptor from shared memory to descBuf
func (q *Queue) getDescBuf(slot int, db descBuf) {
	copy(db, q.i.regions[q.ring.region].data[q.ring.offset+ringSize+slot*descSize:])
}

// putDescBuf copies contents of descriptor buffer into shared memory
func (q *Queue) putDescBuf(slot int, db descBuf) {
	copy(q.i.regions[q.ring.region].data[q.ring.offset+ringSize+slot*descSize:], db)
}

func (db descBuf) getFlags() int {
	return (int)(binary.LittleEndian.Uint16((db)[descFlagsOffset:]))
}

func (db descBuf) getRegion() int {
	return (int)(binary.LittleEndian.Uint16((db)[descRegionOffset:]))
}

func (db descBuf) getLength() int {
	return (int)(binary.LittleEndian.Uint32((db)[descLengthOffset:]))
}

func (db descBuf) getOffset() int {
	return (int)(binary.LittleEndian.Uint32((db)[descOffsetOffset:]))
}

func (db descBuf) getMetadata() int {
	return (int)(binary.LittleEndian.Uint32((db)[descMetadataOffset:]))
}

func (db descBuf) setFlags(val int) {
	binary.LittleEndian.PutUint16((db)[descFlagsOffset:], uint16(val))
}

func (db descBuf) setRegion(val int) {
	binary.LittleEndian.PutUint16((db)[descRegionOffset:], uint16(val))
}

func (db descBuf) setLength(val int) {
	binary.LittleEndian.PutUint32((db)[descLengthOffset:], uint32(val))
}

func (db descBuf) setOffset(val int) {
	binary.LittleEndian.PutUint32((db)[descOffsetOffset:], uint32(val))
}

func (db descBuf) setMetadata(val int) {
	binary.LittleEndian.PutUint32((db)[descMetadataOffset:], uint32(val))
}

/* DESCRIPTOR END */

/* RING BEGIN */

type ringType uint8

const (
	ringTypeS2M ringType = iota
	ringTypeM2S
)

const ringSize = 128

// ring field offsets
const ringCookieOffset = 0
const ringFlagsOffset = 4
const ringHeadOffset = 6
const ringTailOffset = 64

// ringBuf represents a memif ring as array of bytes
type ringBuf []byte

type ring struct {
	ringType ringType
	size     int
	log2Size int
	region   int
	rb       ringBuf
	offset   int
}

// newRing returns new memif ring based on data received in msgAddRing (master only)
func newRing(regionIndex int, ringType ringType, ringOffset int, log2RingSize int) *ring {
	r := &ring{
		ringType: ringType,
		size:     (1 << log2RingSize),
		log2Size: log2RingSize,
		rb:       make(ringBuf, ringSize),
		offset:   ringOffset,
	}

	return r
}

// newRing returns a new memif ring
func (i *Interface) newRing(regionIndex int, ringType ringType, ringIndex int) *ring {
	r := &ring{
		ringType: ringType,
		size:     (1 << i.run.Log2RingSize),
		log2Size: int(i.run.Log2RingSize),
		rb:       make(ringBuf, ringSize),
	}

	rSize := ringSize + descSize*r.size
	if r.ringType == ringTypeS2M {
		r.offset = 0
	} else {
		r.offset = int(i.run.NumQueuePairs) * rSize
	}
	r.offset += ringIndex * rSize

	return r
}

// putRing put the ring to the shared memory
func (q *Queue) putRing() {
	copy(q.i.regions[q.ring.region].data[q.ring.offset:], q.ring.rb)
}

// updateRing updates ring with data from shared memory
func (q *Queue) updateRing() {
	copy(q.ring.rb, q.i.regions[q.ring.region].data[q.ring.offset:])
}

func (r *ring) getCookie() int {
	return (int)(binary.LittleEndian.Uint32((r.rb)[ringCookieOffset:]))
}

// getFlags returns the flags value from ring buffer
// Use Queue.getFlags in fast-path to avoid updating the whole ring.
func (r *ring) getFlags() int {
	return (int)(binary.LittleEndian.Uint16((r.rb)[ringFlagsOffset:]))
}

// getHead returns the head pointer value from ring buffer.
// Use readHead in fast-path to avoid updating the whole ring.
func (r *ring) getHead() int {
	return (int)(binary.LittleEndian.Uint16((r.rb)[ringHeadOffset:]))
}

// getTail returns the tail pointer value from ring buffer.
// Use readTail in fast-path to avoid updating the whole ring.
func (r *ring) getTail() int {
	return (int)(binary.LittleEndian.Uint16((r.rb)[ringTailOffset:]))
}

func (r *ring) setCookie(val int) {
	binary.LittleEndian.PutUint32((r.rb)[ringCookieOffset:], uint32(val))
}

func (r *ring) setFlags(val int) {
	binary.LittleEndian.PutUint16((r.rb)[ringFlagsOffset:], uint16(val))
}

// setHead set the head pointer value int the ring buffer.
// Use writeHead in fast-path to avoid putting the whole ring into shared memory.
func (r *ring) setHead(val int) {
	binary.LittleEndian.PutUint16((r.rb)[ringHeadOffset:], uint16(val))
}

// setTail set the tail pointer value int the ring buffer.
// Use writeTail in fast-path to avoid putting the whole ring into shared memory.
func (r *ring) setTail(val int) {
	binary.LittleEndian.PutUint16((r.rb)[ringTailOffset:], uint16(val))
}

/* RING END */

// isInterrupt returns true if the queue is in interrupt mode
func (q *Queue) isInterrupt() bool {
	return (q.getFlags() & ringFlagInterrupt) == 0
}

// interrupt performs an interrupt if the queue is in interrupt mode
func (q *Queue) interrupt() error {
	if q.isInterrupt() {
		buf := make([]byte, 8)
		binary.PutUvarint(buf, 1)
		n, err := syscall.Write(q.interruptFd, buf[:])
		if err != nil {
			return err
		}
		if n != 8 {
			return fmt.Errorf("Faild to write to eventfd")
		}
	}

	return nil
}