OpenCores
URL https://opencores.org/ocsvn/fade_ether_protocol/fade_ether_protocol/trunk

Subversion Repositories fade_ether_protocol

[/] [fade_ether_protocol/] [trunk/] [stable_jumbo_frames_version/] [linux/] [fpga_l3_fade.c] - Diff between revs 17 and 18

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 17 Rev 18
Line 55... Line 55...
 * packet number - 4 bytes - offset 6
 * packet number - 4 bytes - offset 6
 * transm_delay - 4 bytes - offset 10
 * transm_delay - 4 bytes - offset 10
 * cmd_response - 12 bytes - offset 14
 * cmd_response - 12 bytes - offset 14
 *
 *
 * Total: 26 bytes!
 * Total: 26 bytes!
 
 * If the packet contains "flushed" buffer,
 
 * then data ID is 0xA5A6, and the last word
 
 * contains number of transmitted words.
 
 
 * For command response
 * For command response
 * 0xA55A : cmd_resp ID 2 bytes - offset 2
 * 0xA55A : cmd_resp ID 2 bytes - offset 2
 * 0x0000 : filler - 2 bytes - offset 4
 * 0x0000 : filler - 2 bytes - offset 4
 * cmd_response - 12 bytes offset 6
 * cmd_response - 12 bytes offset 6
Line 71... Line 74...
#define PAYL_LEN ( USER_HDR_LEN + USER_LEN )
#define PAYL_LEN ( USER_HDR_LEN + USER_LEN )
 
 
/* Number of packets in window - this number depends on amount of RAM
/* Number of packets in window - this number depends on amount of RAM
 * in the FPGA - Packets in a widnow must fit in the FPGA RAM
 * in the FPGA - Packets in a widnow must fit in the FPGA RAM
 * Should be power of two! */
 * Should be power of two! */
#define PKTS_IN_WINDOW (1<<5)
#define PKTS_IN_WINDOW (1<<4)
#define PKTS_IN_WINDOW_MASK (PKTS_IN_WINDOW-1)
#define PKTS_IN_WINDOW_MASK (PKTS_IN_WINDOW-1)
 
 
/* Capacity of kernel buffer (mmapped into user space) measured in
/* Capacity of kernel buffer (mmapped into user space) measured in
 * number of windows - should be equal to power of two, to simplify
 * number of windows - should be equal to power of two, to simplify
 * the modulo operation (replacing it by binary AND) */
 * the modulo operation (replacing it by binary AND) */
Line 133... Line 136...
                             of the first packet in the current transmission window */
                             of the first packet in the current transmission window */
  uint32_t pkts[PKTS_IN_WINDOW]; /* This array stores numbers of the last received packets in the
  uint32_t pkts[PKTS_IN_WINDOW]; /* This array stores numbers of the last received packets in the
                                  * transmission window. It is used to avoid unnecessary copying of duplicated
                                  * transmission window. It is used to avoid unnecessary copying of duplicated
                                  * packets into the receiver buffer */
                                  * packets into the receiver buffer */
  rwlock_t flags_lock; //Protects other fields of the slave_data struct
  rwlock_t flags_lock; //Protects other fields of the slave_data struct
 
  uint32_t last_pkt_num; /* Number of the last "flushed" packet */
 
  uint32_t last_pkt_len; /* Number of words in the last "flushed" packet */
  char err_flag;
  char err_flag;
 
  char stopped_flag; /* Flag informing, that transmission has been already terminated */
 
  char eof_flag; /* Flag informing, that all packets are delivered after transmission is terminated */
  char active;
  char active;
  char is_open;
  char is_open;
  int rx_wakeup_thr;
  int rx_wakeup_thr;
  unsigned char mac[ETH_ALEN];
  unsigned char mac[ETH_ALEN];
  struct net_device * dev;
  struct net_device * dev;
Line 159... Line 166...
  return be64_to_cpu(*(uint64_t *)buf);
  return be64_to_cpu(*(uint64_t *)buf);
}
}
 
 
static inline void put_skb_u16(struct sk_buff * skb, uint16_t val)
static inline void put_skb_u16(struct sk_buff * skb, uint16_t val)
{
{
  char * data = skb_put(skb,sizeof(val));
  void * data = skb_put(skb,sizeof(val));
  * (uint16_t *) data = cpu_to_be16(val);
  * (uint16_t *) data = cpu_to_be16(val);
}
}
 
 
static inline void put_skb_u32(struct sk_buff * skb, uint32_t val)
static inline void put_skb_u32(struct sk_buff * skb, uint32_t val)
{
{
  char * data = skb_put(skb,sizeof(val));
  void * data = skb_put(skb,sizeof(val));
  * (uint32_t *) data = cpu_to_be32(val);
  * (uint32_t *) data = cpu_to_be32(val);
}
}
 
 
static inline void put_skb_u64(struct sk_buff * skb, uint64_t val)
static inline void put_skb_u64(struct sk_buff * skb, uint64_t val)
{
{
  char * data = skb_put(skb,sizeof(val));
  void * data = skb_put(skb,sizeof(val));
  * (uint64_t *) data = cpu_to_be64(val);
  * (uint64_t *) data = cpu_to_be64(val);
}
}
 
 
static slave_data * slave_table = NULL;
static slave_data * slave_table = NULL;
 
 
Line 212... Line 219...
  .poll = my_proto1_poll,
  .poll = my_proto1_poll,
  .unlocked_ioctl=my_proto1_ioctl,
  .unlocked_ioctl=my_proto1_ioctl,
  .mmap=my_proto1_mmap
  .mmap=my_proto1_mmap
};
};
 
 
 
 
 
/* Function used to send the user command and wait for confirmation */
 
static inline
 
long send_cmd(slave_data * sd, uint16_t cmd, uint32_t arg, void * resp, int nof_retries, int timeout)
 
{
 
  long result = -ETIMEDOUT;
 
  //Each slave may perform only one user command, so first check, if no other thread
 
  //attempts to send the command
 
  if ( mutex_trylock(&sd->usercmd_lock)==0) return -EBUSY;
 
  //Mutex acquired, we can proceed
 
  //First allocate the sequence number for the command
 
  sd->cmd_seq += 1;
 
  sd->cmd_code = cmd;
 
  sd->cmd_ack = 1; //Mark, that we are waiting for response
 
  //Now in the loop we send the packet, requesting execution of the command
 
  //and then we wait for response with timeout
 
  while(nof_retries--) {
 
    //Send the packet 
 
    struct sk_buff *newskb = NULL;
 
    uint8_t * my_data = NULL;
 
    newskb = alloc_skb(LL_RESERVED_SPACE(sd->dev)+MY_ACK_LEN, GFP_KERNEL);
 
    skb_reserve(newskb,LL_RESERVED_SPACE(sd->dev));
 
    skb_reset_network_header(newskb);
 
    newskb->dev = sd->dev;
 
    newskb->protocol = htons(MY_PROTO_ID);
 
    //Build the MAC header for the new packet
 
    // Tu http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586 jest pokazane jak zbudować pakiet!
 
    if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0)
 
      {
 
        kfree_skb(newskb);
 
        return -EINVAL;
 
      }
 
    //Put the protocol version id to the packet
 
    put_skb_u16(newskb,MY_PROTO_VER);
 
    //Put the command code
 
    put_skb_u16(newskb,cmd);
 
    //Put the sequence number
 
    put_skb_u16(newskb,sd->cmd_seq);
 
    //Put the argument
 
    put_skb_u32(newskb,arg);
 
    //Fill the packet
 
    my_data = skb_put(newskb,MY_ACK_LEN-10);
 
    memset(my_data,0xa5,MY_ACK_LEN-10);
 
    dev_queue_xmit(newskb);
 
    //Sleep with short timeout, waiting for response
 
    if(wait_event_timeout(usercmd_queue,sd->cmd_ack==2,timeout)) {
 
      //Response received
 
      //If target buffer provided, copy data to the userspace buffer
 
      if(resp) memcpy(resp,sd->cmd_resp,12);
 
      result = SUCCESS;
 
      break; //exit loop
 
    }
 
  }
 
  //We don't wait for response any more
 
  sd->cmd_ack = 0;
 
  mutex_unlock(&sd->usercmd_lock);
 
  return result;
 
}
 
 
 
/* Function free_mac may be safely called even if the MAC was not taken
 
   it checks sd->active to detect such situation
 
*/
 
static inline
 
long free_mac(slave_data *sd) {
 
  write_lock_bh(&slave_table_lock);
 
  if(sd->active) {
 
    /* Clear the MAC address */
 
    sd->active = 0;
 
    memset(&sd->mac,0,ETH_ALEN);
 
    write_unlock_bh(&slave_table_lock);
 
    /* Now send the "stop transmission" packet to the slave */
 
    /* Find the net device */
 
    if (!sd->dev) return -ENODEV;
 
    dev_put(sd->dev);
 
    sd->dev=NULL;
 
  } else {
 
    write_unlock_bh(&slave_table_lock);
 
  }
 
  return SUCCESS;
 
}
 
 
static long my_proto1_ioctl (struct file *filp,
static long my_proto1_ioctl (struct file *filp,
                             unsigned int cmd, unsigned long arg)
                             unsigned int cmd, unsigned long arg)
{
{
  slave_data * sd = filp->private_data;
  slave_data * sd = filp->private_data;
  if (_IOC_TYPE(cmd) != L3_V1_IOC_MAGIC) {
  if (_IOC_TYPE(cmd) != L3_V1_IOC_MAGIC) {
Line 241... Line 329...
        return -EFAULT;
        return -EFAULT;
      } else {
      } else {
        read_lock_bh(&sd->ptrs_lock);
        read_lock_bh(&sd->ptrs_lock);
        bp.head=sd->head;
        bp.head=sd->head;
        bp.tail=sd->tail;
        bp.tail=sd->tail;
 
        bp.eof=sd->eof_flag;
        read_unlock_bh(&sd->ptrs_lock);
        read_unlock_bh(&sd->ptrs_lock);
        res2 = __copy_to_user(res,&bp,sizeof(bp));
        res2 = __copy_to_user(res,&bp,sizeof(bp));
        if(res2)
        if(res2)
          return -EFAULT;
          return -EFAULT;
        if (sd->err_flag)
        if (sd->err_flag)
Line 279... Line 368...
      write_unlock_bh(&sd->ptrs_lock);
      write_unlock_bh(&sd->ptrs_lock);
      return SUCCESS;
      return SUCCESS;
    }
    }
  case L3_V1_IOC_STARTMAC: //Open the slave
  case L3_V1_IOC_STARTMAC: //Open the slave
    {
    {
      struct sk_buff *newskb = NULL;
      sd->stopped_flag = 0;
      char * my_data = NULL;
      sd->eof_flag = 0;
      newskb = alloc_skb(LL_RESERVED_SPACE(sd->dev)+MY_ACK_LEN, GFP_KERNEL);
      //We just send a request to start transmission and wait for confirmation
      skb_reserve(newskb,LL_RESERVED_SPACE(sd->dev));
      return send_cmd(sd,FCMD_START,0,NULL,100,2);
      skb_reset_network_header(newskb);
 
      newskb->dev = sd->dev;
 
      newskb->protocol = htons(MY_PROTO_ID);
 
      //Build the MAC header for the new packet
 
      // Based on http://lxr.linux.no/#linux+v3.3.4/net/ipv4/arp.c#L586 !
 
      if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0) {
 
        kfree_skb(newskb);
 
        return -EINVAL;
 
      }
      }
      //Put the protocol version id to the packet
  case L3_V1_IOC_STOPMAC: //Close the slave and reset it to stop transmission immediately
      put_skb_u16(newskb,MY_PROTO_VER);
    {
      //Put the "start" command to the packet
      return send_cmd(sd,FCMD_STOP,0,NULL,100,2);
      put_skb_u16(newskb,0x01);
    }
      my_data = skb_put(newskb,MY_ACK_LEN - 4);
  case L3_V1_IOC_RESETMAC: //Reset MAC so, that it stops transmission immediately
      memset(my_data,0xa5,MY_ACK_LEN - 4);
    {
#ifdef FADE_DEBUG
      return send_cmd(sd,FCMD_RESET,0,NULL,100,2);
      printk(KERN_INFO "skb_nh: %x, skb_dt: %x, skb_nh2: %x, skb_t: %x\n tail: %d head: %d\n",(int)skb_network_header(newskb),(int)newskb->data,
 
             (int)newskb->network_header,(int)newskb->tail, (int)sd->tail, (int)sd->head) ;
 
#endif
 
      dev_queue_xmit(newskb);
 
      return SUCCESS;
 
    }
    }
  case L3_V1_IOC_GETMAC: //Open the slave
  case L3_V1_IOC_GETMAC: //Open the slave
    {
    {
      void * source = (void *) arg;
      void * source = (void *) arg;
      struct l3_v1_slave sl;
      struct l3_v1_slave sl;
Line 346... Line 422...
      sd->dev = dev;
      sd->dev = dev;
      return SUCCESS;
      return SUCCESS;
    }
    }
  case L3_V1_IOC_FREEMAC: //Close the slave and reset it to stop transmission immediately
  case L3_V1_IOC_FREEMAC: //Close the slave and reset it to stop transmission immediately
    {
    {
      write_lock_bh(&slave_table_lock);
      free_mac(sd);
      /* Clear the MAC address */
 
      sd->active = 0;
 
      memset(&sd->mac,0,ETH_ALEN);
 
      write_unlock_bh(&slave_table_lock);
 
      /* Now send the "stop transmission" packet to the slave */
 
      /* Find the net device */
 
      if (!sd->dev) return -ENODEV;
 
      dev_put(sd->dev);
 
      sd->dev=NULL;
 
      return SUCCESS;
 
    }
 
  case L3_V1_IOC_STOPMAC: //Close the slave and reset it to stop transmission immediately
 
    {
 
      struct sk_buff *newskb = NULL;
 
      char * my_data = NULL;
 
      if (!sd->dev) return -ENODEV;
 
      newskb = alloc_skb(LL_RESERVED_SPACE(sd->dev)+MY_ACK_LEN, GFP_ATOMIC);
 
      skb_reserve(newskb,LL_RESERVED_SPACE(sd->dev));
 
      skb_reset_network_header(newskb);
 
      newskb->dev = sd->dev;
 
      newskb->protocol = htons(MY_PROTO_ID);
 
      //Build the MAC header for the new packet
 
      // Based on http://lxr.linux.no/#linux+v3.3.4/net/ipv4/arp.c#L586 !
 
      if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0) {
 
        kfree_skb(newskb);
 
        return -EINVAL;
 
      }
 
      //Put the protocol version id to the packet
 
      put_skb_u16(newskb,MY_PROTO_VER);
 
      //Put the "stop" command to the packet
 
      put_skb_u16(newskb,0x05);
 
      my_data = skb_put(newskb,MY_ACK_LEN - 4);
 
      memset(my_data,0xa5,MY_ACK_LEN - 4);
 
#ifdef FADE_DEBUG
 
      printk(KERN_INFO "skb_nh: %x, skb_dt: %x, skb_nh2: %x, skb_t: %x\n tail: %d head: %d\n",(int)skb_network_header(newskb),(int)newskb->data,
 
             (int)newskb->network_header,(int)newskb->tail, (int)sd->tail, (int)sd->head) ;
 
#endif
 
      dev_queue_xmit(newskb);
 
      dev_put(sd->dev);
 
      sd->dev=NULL;
 
      return SUCCESS;
      return SUCCESS;
    }
    }
  case L3_V1_IOC_USERCMD: //Perform the user command
  case L3_V1_IOC_USERCMD: //Perform the user command
    {
    {
      void * source = (void *) arg;
      void * source = (void *) arg;
Line 401... Line 437...
      if(result) {
      if(result) {
        return -EFAULT;
        return -EFAULT;
      }
      }
      //Now we check if the command is valid user command
      //Now we check if the command is valid user command
      if(ucmd.cmd < 0x0100) return -EINVAL;
      if(ucmd.cmd < 0x0100) return -EINVAL;
      //Each slave may perform only one user command, so first check, if no other thread
      result = send_cmd(sd,ucmd.cmd, ucmd.arg, ucmd.resp, ucmd.nr_of_retries,ucmd.timeout);
      //attempts to send the command
      if(result<0) return result;
      if ( mutex_trylock(&sd->usercmd_lock)==0) return -EBUSY;
 
      //Mutex acquired, we can proceed
 
      //First allocate the sequence number for the command
 
      sd->cmd_seq += 1;
 
      sd->cmd_code = ucmd.cmd;
 
      sd->cmd_ack = 1; //Mark, that we are waiting for response
 
      //Now in the loop we send the packet, requesting execution of the command
 
      //and then we wait for response with timeout
 
      while(ucmd.nr_of_retries--) {
 
        //Send the packet 
 
        struct sk_buff *newskb = NULL;
 
        uint8_t * my_data = NULL;
 
        newskb = alloc_skb(LL_RESERVED_SPACE(sd->dev)+MY_ACK_LEN, GFP_KERNEL);
 
        skb_reserve(newskb,LL_RESERVED_SPACE(sd->dev));
 
        skb_reset_network_header(newskb);
 
        newskb->dev = sd->dev;
 
        newskb->protocol = htons(MY_PROTO_ID);
 
        //Build the MAC header for the new packet
 
        // Tu http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586 jest pokazane jak zbudować pakiet!
 
        if (dev_hard_header(newskb,sd->dev,MY_PROTO_ID,&sd->mac,sd->dev->dev_addr,MY_ACK_LEN+ETH_HLEN) < 0)
 
          {
 
            kfree_skb(newskb);
 
            mutex_unlock(&sd->usercmd_lock);
 
            return -EINVAL;
 
          }
 
        //Put the protocol version id to the packet
 
        put_skb_u16(newskb,MY_PROTO_VER);
 
        //Put the command code
 
        put_skb_u16(newskb,ucmd.cmd);
 
        //Put the sequence number
 
        put_skb_u16(newskb,sd->cmd_seq);
 
        //Put the argument
 
        put_skb_u32(newskb,ucmd.arg);
 
        //Fill the packet
 
        my_data = skb_put(newskb,MY_ACK_LEN-10);
 
        memset(my_data,0xa5,MY_ACK_LEN-10);
 
        dev_queue_xmit(newskb);
 
        //Sleep with short timeout, waiting for response
 
        if(wait_event_timeout(usercmd_queue,sd->cmd_ack==2,ucmd.timeout)) {
 
          //Response received
 
          //Copy data to the userspace buffer
 
          memcpy(&ucmd.resp,sd->cmd_resp,12);
 
          result = __copy_to_user(source,&ucmd,sizeof(ucmd));
          result = __copy_to_user(source,&ucmd,sizeof(ucmd));
          if (result==0){
 
            sd->cmd_ack = 0;
 
            result = SUCCESS;
 
          }
 
          break; //exit loop
 
        }
 
      }
 
      mutex_unlock(&sd->usercmd_lock);
 
      return result;
      return result;
    }
    }
  }
  }
  return -EINVAL;
  return -EINVAL;
}
}
Line 471... Line 457...
  unsigned int data_available;
  unsigned int data_available;
  poll_wait(filp,&read_queue,wait);
  poll_wait(filp,&read_queue,wait);
  read_lock_bh(&sd->ptrs_lock);
  read_lock_bh(&sd->ptrs_lock);
  data_available = (sd->head - sd->tail) & MY_BUF_LEN_MASK;
  data_available = (sd->head - sd->tail) & MY_BUF_LEN_MASK;
  if (data_available>=sd->rx_wakeup_thr) mask |= POLLIN |POLLRDNORM;
  if (data_available>=sd->rx_wakeup_thr) mask |= POLLIN |POLLRDNORM;
 
  if (sd->eof_flag) {
 
    if(data_available) mask |= POLLIN | POLLRDNORM;
 
    else mask |= POLLHUP;
 
  }
#ifdef FADE_DEBUG
#ifdef FADE_DEBUG
  printk(KERN_INFO "poll head: %d tail: %d data: %d prog: %d.\n",sd->head,sd->tail,data_available,sd->rx_wakeup_thr);
  printk(KERN_INFO "poll head: %d tail: %d data: %d prog: %d.\n",sd->head,sd->tail,data_available,sd->rx_wakeup_thr);
#endif
#endif
  //Check if the error occured
  //Check if the error occured
  if (sd->err_flag) mask |= POLLERR;
  if (sd->err_flag) mask |= POLLERR;
Line 619... Line 609...
  slave_data * sd = NULL;
  slave_data * sd = NULL;
  int32_t pkt_dist;
  int32_t pkt_dist;
  char * my_data = NULL;
  char * my_data = NULL;
  unsigned char tmp_buf[USER_HDR_LEN];
  unsigned char tmp_buf[USER_HDR_LEN];
  char ack_packet = 0; //Should we acknowledge the packet?
  char ack_packet = 0; //Should we acknowledge the packet?
 
  uint32_t pkt_pos, needed_space, buf_free;
  //Extract the MAC header from the received packet
  //Extract the MAC header from the received packet
  rcv_hdr=eth_hdr(skb);
  rcv_hdr=eth_hdr(skb);
  //First we try to identify the sender so we search the table of active slaves
  //First we try to identify the sender so we search the table of active slaves
  //The table is protected during the search, so it should not be changed
  //The table is protected during the search, so it should not be changed
#ifdef FADE_DEBUG
#ifdef FADE_DEBUG
Line 659... Line 650...
    // Here is shown how to build a packet: http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586
    // Here is shown how to build a packet: http://lxr.linux.no/linux+*/net/ipv4/arp.c#L586
    if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
    if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
      goto error;
      goto error;
    //Put the protocol version id to the packet
    //Put the protocol version id to the packet
    put_skb_u16(newskb,MY_PROTO_VER);
    put_skb_u16(newskb,MY_PROTO_VER);
    //Put the "restart" command to the packet
    //Put the "restart" command to the packet, which should force it to stop transmission
    put_skb_u16(newskb,0x05);
    //immediately
 
    put_skb_u16(newskb,FCMD_RESET);
    my_data = skb_put(newskb,MY_ACK_LEN - 4);
    my_data = skb_put(newskb,MY_ACK_LEN - 4);
    memset(my_data,0xa5,MY_ACK_LEN - 4);
    memset(my_data,0xa5,MY_ACK_LEN - 4);
    dev_queue_xmit(newskb);
    dev_queue_xmit(newskb);
    kfree_skb(skb);
    kfree_skb(skb);
    return NET_RX_DROP;
    return NET_RX_DROP;
Line 677... Line 669...
  //To avoid problems with scattered packets, we copy initial part of data to the buffer
  //To avoid problems with scattered packets, we copy initial part of data to the buffer
  //using the skb_copy_bits
  //using the skb_copy_bits
  skb_copy_bits(skb,0,tmp_buf,USER_HDR_LEN);
  skb_copy_bits(skb,0,tmp_buf,USER_HDR_LEN);
  /* We extract the information from the user header
  /* We extract the information from the user header
   * First we check if this is correct version of the protocol */
   * First we check if this is correct version of the protocol */
  if (unlikely(get_be_u16(&tmp_buf[0]) != MY_PROTO_VER))
  if (unlikely(get_be_u16(&tmp_buf[0]) != MY_PROTO_VER)) goto wrong_pkt_type_error;
    goto wrong_pkt_type_error;
 
  if (unlikely(get_be_u16(&tmp_buf[2]) == 0xa55a)) {
  if (unlikely(get_be_u16(&tmp_buf[2]) == 0xa55a)) {
    //This is a command response packet
    //This is a command response packet
    printk(KERN_INFO " received command response packet");
    printk(KERN_INFO " received command response packet");
    if(sd->cmd_ack==1) {
    if(sd->cmd_ack==1) {
      //We are waiting for response
      //We are waiting for response
Line 699... Line 690...
      }
      }
    }
    }
    kfree_skb(skb);
    kfree_skb(skb);
    return NET_RX_SUCCESS;
    return NET_RX_SUCCESS;
  }
  }
  if (unlikely(get_be_u16(&tmp_buf[2]) != 0xa5a5)) {
  if (unlikely((get_be_u16(&tmp_buf[2]) != 0xa5a5) &&
 
               (get_be_u16(&tmp_buf[2]) != 0xa5a6))
 
      ) {
    //This is not a data packet
    //This is not a data packet
    goto wrong_pkt_type_error;
    goto wrong_pkt_type_error;
  }
  }
  /* Now we handle the data packet
  /* Now we handle the data packet
     PLEASE NOTE, THAT THIS MUST TIGHTLY CORRESPOND
     PLEASE NOTE, THAT THIS MUST TIGHTLY CORRESPOND
Line 728... Line 721...
  /* To know if this is a new packet, we compare the packet number
  /* To know if this is a new packet, we compare the packet number
   * in the received packet with the number of the last unconfirmed packet,
   * in the received packet with the number of the last unconfirmed packet,
   * calculating the difference between those two numbers: */
   * calculating the difference between those two numbers: */
  read_lock_bh(&sd->pkts_rwlock);
  read_lock_bh(&sd->pkts_rwlock);
  pkt_dist=(int32_t) packet_number - (int32_t) sd->last_nack_pkt;
  pkt_dist=(int32_t) packet_number - (int32_t) sd->last_nack_pkt;
  //Check if this packet was already received
  //Check if this packet was received before
  is_duplicate=(sd->pkts[packet_number & PKTS_IN_WINDOW_MASK] == packet_number) ? 1 : 0;
  is_duplicate=(sd->pkts[packet_number & PKTS_IN_WINDOW_MASK] == packet_number) ? 1 : 0;
  read_unlock_bh(&sd->pkts_rwlock);
  read_unlock_bh(&sd->pkts_rwlock);
  if (likely((pkt_dist>=0) && (pkt_dist<PKTS_IN_WINDOW))) {
  if (unlikely((pkt_dist<0) || (pkt_dist>=PKTS_IN_WINDOW))) {
    /* This is the expected data packet. */
    //This is a "too old" packet, or packet "from the future", which should not be transimtted
 
    //by the FPGA
 
    if (pkt_dist<0) {
 
      // This is a packet which was already confirmed, but probably ACK was lost
 
#ifdef FADE_DEBUG
 
      printk(KERN_INFO "Packet already confirmed: pkt=%d expect=%d last=%d\n",packet_number, sd->pkts[packet_number], sd->last_nack_pkt);
 
#endif
 
      ack_packet = 1;
 
      goto confirm;
 
    } else {
 
      /* This is a packet with too high set number (packet "from the future"
 
       * it my be a symptom of serious communication problem! */
 
      printk(KERN_ERR "Packet from the future! number: %d last_confirmed: %d\n", packet_number, sd->last_nack_pkt);
 
      goto error2;
 
    }
 
  }
 
  //If we get there, it means, that:
 
  //   pkt_dist >= 0 and pkt_dist < PKTS_IN_WINDOW
 
  // So this is an expected data packet.
    if(is_duplicate) {
    if(is_duplicate) {
      //Packet already confirmed, probably the ACK was lost, so simply generate the ACK
      //Packet already confirmed, probably the ACK was lost, so simply generate the ACK
      ack_packet = 1;
      ack_packet = 1;
    } else {
    goto confirm;
      //First check, if there is a free space to copy data
  }
      uint32_t pkt_pos, needed_space, buf_free;
  //Packet not confirmed yet. Confirm it only after all processing is successfully completed
      pkt_pos=(packet_number<<LOG2_USER_LEN) & MY_BUF_LEN_MASK;
      pkt_pos=(packet_number<<LOG2_USER_LEN) & MY_BUF_LEN_MASK;
      //We must be sure, that the pointers do not change during this check
      //We must be sure, that the pointers do not change during this check
      read_lock_bh(&sd->ptrs_lock);
      read_lock_bh(&sd->ptrs_lock);
      //Calculate free space needed to copy the packet
      //Calculate free space needed to copy the packet
      needed_space = (pkt_pos+USER_LEN-1-(sd->head)) & MY_BUF_LEN_MASK;
      needed_space = (pkt_pos+USER_LEN-1-(sd->head)) & MY_BUF_LEN_MASK;
Line 751... Line 762...
#ifdef FADE_DEBUG
#ifdef FADE_DEBUG
      printk(KERN_INFO "packet_nr: %d Free buffer: %d needed space: %d head=%d last_nack=%d\n",
      printk(KERN_INFO "packet_nr: %d Free buffer: %d needed space: %d head=%d last_nack=%d\n",
             packet_number, needed_space, buf_free, sd->head, sd->last_nack_pkt);
             packet_number, needed_space, buf_free, sd->head, sd->last_nack_pkt);
#endif
#endif
      read_unlock_bh(&sd->ptrs_lock);
      read_unlock_bh(&sd->ptrs_lock);
      if (likely( buf_free > needed_space )) {
  if (unlikely( buf_free <= needed_space )) goto error2; //No place for copying, drop the packet
        // Check the length of the package
        // Check the length of the package
        if (unlikely(skb->len != PAYL_LEN)) {
        if (unlikely(skb->len != PAYL_LEN)) {
          printk(KERN_ERR "Error! Length of data should be %d but is %d!\n",PAYL_LEN, skb->len);
          printk(KERN_ERR "Error! Length of data should be %d but is %d!\n",PAYL_LEN, skb->len);
          sd->err_flag |= FADE_ERR_INCORRECT_LENGTH;
          sd->err_flag |= FADE_ERR_INCORRECT_LENGTH;
          kfree_skb(skb);
    goto error2;
          return NET_RX_DROP;
 
        }
        }
        // We can safely copy all the packet to the buffer:
        // We can safely copy all the packet to the buffer:
        res = skb_copy_bits(skb,USER_HDR_LEN,&(sd->buffer[pkt_pos]),USER_LEN);
        res = skb_copy_bits(skb,USER_HDR_LEN,&(sd->buffer[pkt_pos]),USER_LEN);
#ifdef FADE_DEBUG
#ifdef FADE_DEBUG
        printk(KERN_INFO " skb_copy_bits: %d", res);
        printk(KERN_INFO " skb_copy_bits: %d", res);
#endif
#endif
 
  if (res<0) goto error2; //Unsuccessfull copying
        //Packet was copied, so note, that we should confirm it
        //Packet was copied, so note, that we should confirm it
        if (res>=0) {
 
          ack_packet=1;
          ack_packet=1;
 
  /* When packet is copied, we can check if this is the last "flushed" packet */
 
  if (get_be_u16(&tmp_buf[2])==0xa5a6) {
 
    //Flushed packet, store its number and length (should it be protected with spinlock?)
 
    sd->last_pkt_num = packet_number;
 
    //Copy the length, truncating it from 64 bits
 
    sd->last_pkt_len = (uint32_t) * (uint64_t *) &(sd->buffer[pkt_pos+USER_LEN-sizeof(uint64_t)]);
 
    //We have received the "flushed" buffer, mark that transmission is stopped
 
    sd->stopped_flag = 1;
 
  }
          /* We modify the number of the copied packet in the pkts array, to avoid
          /* We modify the number of the copied packet in the pkts array, to avoid
           * unnecessary copying if we receive a duplicate
           * unnecessary copying if we receive a duplicate
           * To modify the pkts table, we must close pkts_rwlock for writing */
           * To modify the pkts table, we must close pkts_rwlock for writing */
          write_lock_bh(&sd->pkts_rwlock);
          write_lock_bh(&sd->pkts_rwlock);
          sd->pkts[packet_number & PKTS_IN_WINDOW_MASK]= packet_number;
          sd->pkts[packet_number & PKTS_IN_WINDOW_MASK]= packet_number;
Line 786... Line 805...
              if (sd->pkts[(sd->last_nack_pkt + count) & PKTS_IN_WINDOW_MASK] != chk_packet_num) break; //Packet not confirmed
              if (sd->pkts[(sd->last_nack_pkt + count) & PKTS_IN_WINDOW_MASK] != chk_packet_num) break; //Packet not confirmed
              chk_packet_num++;
              chk_packet_num++;
            }
            }
            sd->last_nack_pkt += count;
            sd->last_nack_pkt += count;
            write_unlock_bh(&sd->pkts_rwlock);
            write_unlock_bh(&sd->pkts_rwlock);
            /* Now we can move the head position right after the last serviced packet */
    /* Now we can move the head position */
 
    if(likely((sd->stopped_flag == 0) ||
 
              ((uint32_t)(sd->last_nack_pkt-1) != sd->last_pkt_num))) {
 
      //Normal packet, set head right after the last serviced packet
            write_lock_bh(&sd->ptrs_lock);
            write_lock_bh(&sd->ptrs_lock);
            sd->head = (sd->last_nack_pkt*USER_LEN) & MY_BUF_LEN_MASK;
            sd->head = (sd->last_nack_pkt*USER_LEN) & MY_BUF_LEN_MASK;
            /* When we have moved the head pointer, we can try to wake up the reading processes */
      //Now try to wake up the reading process
 
      if (((sd->head - sd->tail) & MY_BUF_LEN_MASK) >= sd->rx_wakeup_thr)
            wake_up_interruptible(&read_queue);
            wake_up_interruptible(&read_queue);
            write_unlock_bh(&sd->ptrs_lock);
 
          } else {
          } else {
            // It was not the last packet, no need to move the head pointer
      //Flushed packet, set head right after the end of the packet
 
      write_lock_bh(&sd->ptrs_lock);
 
      sd->head = ((sd->last_nack_pkt-1)*USER_LEN+sd->last_pkt_len) & MY_BUF_LEN_MASK;
 
      //We have consumed the last, "flushed" buffer, so now we can set the eof flag
 
      sd-> eof_flag = 1;
 
      //And we wake up the reading process
 
      wake_up_interruptible(&read_queue);
 
    } //if - stopped_flag
 
    write_unlock_bh(&sd->ptrs_lock);
 
  } else { // if - last_nack_pkt 
            write_unlock_bh(&sd->pkts_rwlock);
            write_unlock_bh(&sd->pkts_rwlock);
          }
          }
        }
 confirm:
      }
  //Send the confirmation if required
    }
 
  } else {
 
    /* This packet has incorrect set number. If the number is too low, we ignore the packet,
 
     * but send the confirmation (ack was received too late, or was lost?) */
 
    if (pkt_dist<0) {
 
      ack_packet = 1;
 
#ifdef FADE_DEBUG
 
      printk(KERN_INFO "Packet already confirmed: pkt=%d expect=%d last=%d\n",packet_number, sd->pkts[packet_number], sd->last_nack_pkt);
 
#endif
 
    } else {
 
      /* This is a packet with too high set number (packet "from the future"
 
       * it my be a symptom of serious communication problem! */
 
      printk(KERN_ERR "Packet from the future! number: %d last_confirmed: %d\n", packet_number, sd->last_nack_pkt);
 
    }
 
  }
 
  //Now send the confirmation
 
  if (likely(ack_packet)) {
  if (likely(ack_packet)) {
    newskb = alloc_skb(LL_RESERVED_SPACE(dev)+MY_ACK_LEN, GFP_ATOMIC);
    newskb = alloc_skb(LL_RESERVED_SPACE(dev)+MY_ACK_LEN, GFP_ATOMIC);
    skb_reserve(newskb,LL_RESERVED_SPACE(dev));
    skb_reserve(newskb,LL_RESERVED_SPACE(dev));
    skb_reset_network_header(newskb);
    skb_reset_network_header(newskb);
    newskb->dev = dev;
    newskb->dev = dev;
Line 827... Line 842...
    if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
    if (dev_hard_header(newskb,dev,MY_PROTO_ID,&rcv_hdr->h_source,&rcv_hdr->h_dest,MY_ACK_LEN+ETH_HLEN) < 0)
      goto error;
      goto error;
    //Put the protocol version id to the packet
    //Put the protocol version id to the packet
    put_skb_u16(newskb,MY_PROTO_VER);
    put_skb_u16(newskb,MY_PROTO_VER);
    //Put the "ACKNOWLEDGE" type
    //Put the "ACKNOWLEDGE" type
    put_skb_u16(newskb,0x03);    //ACK!
    put_skb_u16(newskb,FCMD_ACK);
    //Copy the begining of the received packet to the acknowledge packet
    //Copy the begining of the received packet to the acknowledge packet
    my_data = skb_put(newskb,MY_ACK_COPIED);
    my_data = skb_put(newskb,MY_ACK_COPIED);
    res = skb_copy_bits(skb,4,my_data,MY_ACK_COPIED);
    res = skb_copy_bits(skb,4,my_data,MY_ACK_COPIED);
    my_data = skb_put(newskb,MY_ACK_LEN -MY_ACK_COPIED-4);
    my_data = skb_put(newskb,MY_ACK_LEN -MY_ACK_COPIED-4);
    memset(my_data,0xa5,MY_ACK_LEN - MY_ACK_COPIED-4);
    memset(my_data,0xa5,MY_ACK_LEN - MY_ACK_COPIED-4);
Line 853... Line 868...
  } else {
  } else {
    printk(KERN_ERR "FADE: wrong_pkt_type_error called with null sd");
    printk(KERN_ERR "FADE: wrong_pkt_type_error called with null sd");
  }
  }
 error:
 error:
  if (newskb) kfree_skb(newskb);
  if (newskb) kfree_skb(newskb);
 
 error2:
  if (skb) kfree_skb(skb);
  if (skb) kfree_skb(skb);
  return NET_RX_DROP;
  return NET_RX_DROP;
}
}
 
 
/*
/*
Line 887... Line 903...
  if (!sd->buffer) return -ENOMEM;
  if (!sd->buffer) return -ENOMEM;
  //Set the MAC address to 0
  //Set the MAC address to 0
  memset(sd->mac,0,sizeof(sd->mac));
  memset(sd->mac,0,sizeof(sd->mac));
  sd->head = 0;
  sd->head = 0;
  sd->tail = 0;
  sd->tail = 0;
 
  sd->eof_flag = 0;
 
  sd->stopped_flag = 0;
  sd->err_flag = 0;
  sd->err_flag = 0;
  sd->last_nack_pkt = 0;
  sd->last_nack_pkt = 0;
  sd->rx_wakeup_thr = 1;
  sd->rx_wakeup_thr = 1;
  sd->active = 0;
  sd->active = 0;
  sd->cmd_seq = 0;
  sd->cmd_seq = 0;
Line 902... Line 920...
 
 
static int my_proto1_release(struct inode *inode,
static int my_proto1_release(struct inode *inode,
                             struct file *file)
                             struct file *file)
{
{
  slave_data * sd = file->private_data;
  slave_data * sd = file->private_data;
#ifdef FADE_DEBUG
  //#ifdef FADE_DEBUG
  printk (KERN_INFO "device_release(%p,%p)\n", inode, file);
  printk (KERN_INFO "device_release(%p,%p)\n", inode, file);
#endif
  //#endif
  //Release resources associated with servicing of the particular device
  //Release resources associated with servicing of the particular device
  if (sd) {
  if (sd) {
    if (sd->is_open) {
    if (sd->is_open) {
      sd->is_open = 0; //It can be dangerous! Before freeing the buffer, we must be sure, that
      sd->is_open = 0; //It can be dangerous! Before freeing the buffer, we must be sure, that
      //no our packet is being processed!
      //no our packet is being processed!
      if (sd->active) {
      printk (KERN_INFO "freed MAC\n");
        sd->active = 0;
      free_mac(sd); //It also sets sd->active to 0!
      }
 
      if (sd->buffer) {
      if (sd->buffer) {
 
        printk (KERN_INFO "freed buffer\n");
        vfree(sd->buffer);
        vfree(sd->buffer);
        sd->buffer = NULL;
        sd->buffer = NULL;
      }
      }
    }
    }
  }
  }

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.