📄 buf.c
字号:
/*************************************************************************** * buf.c - Implement the buffering of the ip-packets * ------------------- * begin : 2003 * authors : Linus Gasser * emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** * Changes * ------- * date - name - description * 03/05/02 - ineiti - start * **************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//* ------------------------------------------------------------------------ * -----------------------------------------------------------------------*/#include "spc.h"#include "system.h"#include "tcpip.h"#include "net.h"#include "buf.h"#include "ack.h"#define DBG_LVL 1/** * @short initialise the buffers * * Initialises enough memory for a couple of IP-packets... * * @param buf where all the stuff shall be stored */void buf_init( struct buffer_t *buf ) { buf->ip_buf_rcv = swr_malloc( IP_BUF_LEN ); buf->ip_buf_rcv_pos = 0; buf->ip_buf_send = swr_malloc( IP_BUF_LEN ); buf->ip_buf_send_pos = 0; ack_init( &buf->ack_sent ); ack_init( &buf->ack_rcvd ); ack_init( &buf->rcvd ); ack_init( &buf->send );}/** * Clean up the buffers */void buf_cleanup( struct buffer_t *buf ) { if ( buf ) { swr_free( buf->ip_buf_rcv ); swr_free( buf->ip_buf_send ); ack_free( &buf->ack_sent ); ack_free( &buf->ack_rcvd ); ack_free( &buf->rcvd ); ack_free( &buf->send ); }}/** * @short update the references * * When receiving an acknowledge over the air, we can delete some * references from our table... * * TODO: is it possible to have two acks with same pos but different * length? * * @param buf the buffer-structure * @param pack what to remove */void buf_update_ack_sent( struct buffer_t *buf, struct rf_packet *pack ) { if ( !buf->ack_sent->len ) { PR_DBG( 0, "Receiving acknowledge while no waiting acks!\n" ); } else { if ( ack_delete( buf->ack_sent, pack->pos ) < 0 ) { PR_DBG( 0, "Couldn't find the packet to ack!\n" ); } }}/** * @short copies b to a with wrap-over in the destination * * Copies b to a and takes care about an eventual overflow in the * destination block. It then returns the new position. * * @param a destination * @param b source * @param pos the position in the destination * @param len how many bytes * @param wrap the size of the destination * @return the new position in the destination */int buf_copy_wrap_dst( void *a, void *b, int pos, int len, int wrap ) { int ret; if ( pos + len > wrap ) { // Do some magick on the boundaries ret = wrap - pos; memcpy( a + pos, b, ret ); memcpy( a, b + ret, len - ret ); ret = len - ret; } else { memcpy( a + pos, b, len ); ret = pos + len; } return ret;}/** * @short copies b to a with wrap-over in the source * * Copies b to a and takes care about an eventual overflow in the * source block. It then returns the new position. * * @param a destination * @param b source * @param pos the position in the source * @param len how many bytes * @param wrap the size of the source * @return the new position in the source */int buf_copy_wrap_src( void *a, void *b, int pos, int len, int wrap ) { int ret; if ( pos + len > wrap ) { // Do some magick on the boundaries ret = wrap - pos; memcpy( a, b + pos, ret ); memcpy( a + ret, b, len - ret ); ret = len - ret; } else { memcpy( a, b + pos, len ); ret = pos + len; } return ret;}/** * @short inserts a rf-packet in the buffer * * Puts together received data that comes from the rf-interface. * Also inserts acks in the list and calls the kernel-rx * function if a packet has been received successfully. * * @param buf the buffer-structure * @param pack the received packet */void buf_rf_to_net( struct buffer_t *buf, struct rf_packet *pack ) { struct ack *a; char *block; int ip_len, half, pa, pb; // Copy the received data in the ip-buffer buf_copy_wrap_dst( buf->ip_buf_rcv, &pack->data, pack->pos, pack->len, IP_BUF_LEN ); // Append in the ack_rcvd ack_append( buf->ack_rcvd, pack->pos, pack->len ); // Look if the packet is new or resent due to a lost ack half = IP_BUF_LEN / 2; pa = pack->pos; pb = buf->ip_buf_rcv_pos; if ( ( ( pa >= pb ) && ( pa - pb >= half ) ) || ( ( pa < pb ) && ( pb - pa <= half ) ) ) { PR_DBG( 1, "Rejected packet because it already got processed\n" ); // Reject packet } else { PR_DBG( 4, "Incoming: %i, last good: %i\n", pack->pos, buf->ip_buf_rcv_pos ); // Append in the rcvd list ack_ins_sorted( buf->rcvd, pack->pos, pack->len ); // Search if we have already enough bytes to build a ip-packet a = ack_join_blocks( buf->rcvd ); if ( a->len > 2 ) { PR_DBG( 4, "Received a block of len %i and allocating\n", a->len ); block = swr_malloc( a->len ); buf->ip_buf_rcv_pos = buf_copy_wrap_src( block, buf->ip_buf_rcv, a->pos, a->len, IP_BUF_LEN ); ip_len = *((u16*)block); if ( ip_len <= a->len ) { PR_DBG( 1, "Block contains at least one ip-packet with len %i and CRC %x\n", ip_len, *((U32*)( block + 2 ) ) ); // If we have enough data, we cut a packet from the beginnning // but without the length-indicator and send it to the kernel net_send_to_kernel( buf->dev, block + 2, ip_len ); ack_cut_begin( buf->rcvd, ip_len + 2 ); } swr_free( block ); } }}/** * @short prepare a packet over the air * */void buf_net_to_rf( struct buffer_t *buf, char *packet, int len ) { PR_DBG( 1, "Putting packet to rf, len:%i\n", len ); // Add it to the packets to send ack_append( buf->send, buf->ip_buf_send_pos, len ); // And copy the data to send into the ring-buffer buf->ip_buf_send_pos = buf_copy_wrap_dst( buf->ip_buf_send, packet, buf->ip_buf_send_pos, len, IP_BUF_LEN );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -