blob: 30fdf853cbf9d231d359ee5b6e9221a51187cb8a [file] [log] [blame]
/**************************************************************************
*
* Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. The name of Kip Macy nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*
***************************************************************************/
#ifndef _SHMBUF_RING_H_
#define _SHMBUF_RING_H_
#include <machine/bsd_cpu.h>
#include <sys/bsd_mbuf.h>
#include <netinet/bsd_in.h>
#include <unistd.h>
#include <pthread.h>
#include "if_host.h"
#include "host_serv.h"
extern void mtx_lock(struct mtx *m);
extern void mtx_unlock(struct mtx * m);
struct shm_bufring {
char buf[HIF_SHMBUF_SIZE*HIF_MAX_SHMBUF];
volatile int read_off;
volatile int write_off;
char pad[4088];
};
#if 0
struct shm_bufring {
volatile uint32_t br_prod_head;
volatile uint32_t br_prod_tail;
int br_prod_size;
int br_prod_mask;
uint64_t br_drops;
uint64_t br_prod_bufs;
uint64_t br_prod_bytes;
/*
* Pad out to next L2 cache line
*/
uint64_t _pad0[11];
volatile uint32_t br_cons_head;
volatile uint32_t br_cons_tail;
int br_cons_size;
int br_cons_mask;
/*
* Pad out to next L2 cache line
*/
uint64_t _pad1[14];
//#ifdef DEBUG_SHMBUFRING
struct mtx *br_lock;
//#endif
void *br_ring[0];
};
#endif //0
static inline int shm_bufring_enqueue(struct shm_bufring *br, struct mbuf* m)
{
struct mbuf *mm;
char *shmbuf, *buf_ptr;
int next_off = (br->write_off + 1) % HIF_MAX_SHMBUF;
/* wait for the full case */
while(next_off == br->read_off)
next_off = (br->write_off + 1) % HIF_MAX_SHMBUF;
shmbuf = br->buf + HIF_SHMBUF_SIZE * br->write_off;
/* copy data into shm buffer*/
if(m->m_next == NULL){
/* send out the packet*/
bcopy(m->m_data, shmbuf, m->m_pkthdr.len);
} else {
buf_ptr = shmbuf;
for(mm = m; mm != NULL; mm = mm->m_next){
bcopy(mtod(mm, void *), (void*)buf_ptr, mm->m_len);
buf_ptr += mm->m_len;
}
}
/* update buffer*/
br->write_off = (br->write_off + 1) % HIF_MAX_SHMBUF;
return 0;
}
/*
* single-consumer dequeue
* use where dequeue is protected by a lock
* e.g. a network driver's tx queue lock
*/
static inline int shm_bufring_dequeue(struct shm_bufring *br, char* buf, int len)
{
unsigned short pkt_len;
char *pkt_ptr;
int waited = 0;
/* wait for the empty case */
while(br->read_off == br->write_off){
if(waited == 0){
host_thread_enter_wait_region();
waited = 1;
}
usleep(1);
}
if(waited == 1){
host_thread_exit_wait_region();
waited = 0;
}
pkt_ptr = br->buf + HIF_SHMBUF_SIZE * br->read_off;
/* copy data from shm to mbuf*/
pkt_len = ntohs(*((unsigned short*)(pkt_ptr+2)));
//pkt_len = (pkt_len << 8) | pkt_ptr[3];
if(pkt_len > len){
return 0;
} else{
bcopy(pkt_ptr, buf, pkt_len);
br->read_off = (br->read_off + 1) % HIF_MAX_SHMBUF;
return pkt_len;
}
}
#endif