コード例 #1
0
ファイル: netif.c プロジェクト: Minjunhao/RKB-DM8100
/**
 * Call netif_poll() in the main loop of your application. This is to prevent
 * reentering non-reentrant functions like tcp_input(). Packets passed to
 * netif_loop_output() are put on a list that is passed to netif->input() by
 * netif_poll().
 */
void
netif_poll(struct netif *netif)
{
  struct pbuf *in;
  SYS_ARCH_DECL_PROTECT(lev);

  do {
    /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
    SYS_ARCH_PROTECT(lev);
    in = netif->loop_first;
    if(in != NULL) {
      struct pbuf *in_end = in;
#if LWIP_LOOPBACK_MAX_PBUFS
      u8_t clen = pbuf_clen(in);
      /* adjust the number of pbufs on queue */
      LWIP_ASSERT("netif->loop_cnt_current underflow",
        ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
      netif->loop_cnt_current -= clen;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
      while(in_end->len != in_end->tot_len) {
        LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
        in_end = in_end->next;
      }
      /* 'in_end' now points to the last pbuf from 'in' */
      if(in_end == netif->loop_last) {
        /* this was the last pbuf in the list */
        netif->loop_first = netif->loop_last = NULL;
      } else {
        /* pop the pbuf off the list */
        netif->loop_first = in_end->next;
        LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
      }
      /* De-queue the pbuf from its successors on the 'loop_' list. */
      in_end->next = NULL;
    }
    SYS_ARCH_UNPROTECT(lev);

    if(in != NULL) {
      /* loopback packets are always IP packets! */
      if(ip_input(in, netif) != ERR_OK) {
        pbuf_free(in);
      }
      /* Don't reference the packet any more! */
      in = NULL;
    }
  /* go on while there is a packet on the list */
  } while(netif->loop_first != NULL);
}
コード例 #2
0
int xaxiemacif_input(struct netif *netif)
{
	struct eth_hdr *ethhdr;
	struct pbuf *p;
	SYS_ARCH_DECL_PROTECT(lev);

	/* move received packet into a new pbuf */
	SYS_ARCH_PROTECT(lev);
	p = low_level_input(netif);
	SYS_ARCH_UNPROTECT(lev);

	/* no packet could be read, silently ignore this */
	if (p == NULL)
		return 0;

	/* points to packet payload, which starts with an Ethernet header */
	ethhdr = p->payload;

#if LINK_STATS
	lwip_stats.link.recv++;
#endif /* LINK_STATS */

	switch (htons(ethhdr->type)) {
		/* IP or ARP packet? */
		case ETHTYPE_IP:
		case ETHTYPE_ARP:
#if PPPOE_SUPPORT
			/* PPPoE packet? */
		case ETHTYPE_PPPOEDISC:
		case ETHTYPE_PPPOE:
#endif /* PPPOE_SUPPORT */
			/* full packet send to tcpip_thread to process */
			if (netif->input(p, netif) != ERR_OK) {
				LWIP_DEBUGF(NETIF_DEBUG, ("xaxiemacif_input: IP input error\r\n"));
				pbuf_free(p);
				p = NULL;
			}
			break;

		default:
			pbuf_free(p);
			p = NULL;
			break;
	}

	return 1;
}
コード例 #3
0
ファイル: mem.c プロジェクト: networkextension/A.BIG.T
/**
 * Put a struct mem back on the heap
 *
 * @param rmem is the data portion of a struct mem as returned by a previous
 *             call to mem_malloc()
 */
void
mem_free(void *rmem)
{
  struct mem *mem;
  LWIP_MEM_FREE_DECL_PROTECT();

  if (rmem == NULL) {
    LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("mem_free(p == NULL) was called.\n"));
    return;
  }
  LWIP_ASSERT("mem_free: sanity check alignment", (((mem_ptr_t)rmem) & (MEM_ALIGNMENT-1)) == 0);

  LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
    (u8_t *)rmem < (u8_t *)ram_end);

  if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
    SYS_ARCH_DECL_PROTECT(lev);
    LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_free: illegal memory\n"));
    /* protect mem stats from concurrent access */
    SYS_ARCH_PROTECT(lev);
    MEM_STATS_INC(illegal);
    SYS_ARCH_UNPROTECT(lev);
    return;
  }
  /* protect the heap from concurrent access */
  LWIP_MEM_FREE_PROTECT();
  /* Get the corresponding struct mem ... */
  mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
  /* ... which has to be in a used state ... */
  LWIP_ASSERT("mem_free: mem->used", mem->used);
  /* ... and is now unused. */
  mem->used = 0;

  if (mem < lfree) {
    /* the newly freed struct is now the lowest */
    lfree = mem;
  }

  MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));

  /* finally, see if prev or next are free also */
  plug_holes(mem);
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
  mem_free_count = 1;
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
  LWIP_MEM_FREE_UNPROTECT();
}
コード例 #4
0
ファイル: lwip_drv.cpp プロジェクト: bratkov/tmos
/**
 * This function with either place the packet into the Stellaris transmit fifo,
 * or will place the packet in the interface PBUF Queue for subsequent
 * transmission when the transmitter becomes idle.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 */
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
	LWIP_DRIVER_DATA* drv_data = (LWIP_DRIVER_DATA*)netif;
	MAC_Type* mac = (MAC_Type*)netif->state;
	SYS_ARCH_DECL_PROTECT(lev);

	/**
	 * This entire function must run within a "critical section" to preserve
	 * the integrity of the transmit pbuf queue.
	 *
	 */
	SYS_ARCH_PROTECT(lev);

	/**
	 * Bump the reference count on the pbuf to prevent it from being
	 * freed till we are done with it.
	 *
	 */
	pbuf_ref(p);

	/**
	 * If the transmitter is idle, and there is nothing on the queue,
	 * send the pbuf now.
	 *
	 */
	if (PBUF_QUEUE_EMPTY(&drv_data->txq) && ((mac->MACTR & MAC_TR_NEWTX) == 0))
	{
		low_level_transmit(netif, p);
	}

	/* Otherwise place the pbuf on the transmit queue. */
	else
	{
		/* Add to transmit packet queue */
		if (!enqueue_packet(p, &drv_data->txq))
		{
			/* if no room on the queue, free the pbuf reference and return error. */
			pbuf_free(p);
			SYS_ARCH_UNPROTECT(lev);
			return (ERR_MEM);
		}
	}

	/* Return to prior interrupt state and return. */
	SYS_ARCH_UNPROTECT(lev);
	return (ERR_OK);
}
コード例 #5
0
ファイル: stellarisif.c プロジェクト: KS10FPGA/KS10FPGA
/**
 * This function with either place the packet into the Stellaris transmit fifo,
 * or will place the packet in the interface PBUF Queue for subsequent
 * transmission when the transmitter becomes idle.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 */
static err_t
stellarisif_output(struct netif *netif, struct pbuf *p)
{
  struct stellarisif *stellarisif = netif->state;
  SYS_ARCH_DECL_PROTECT(lev);

  /**
   * This entire function must run within a "critical section" to preserve
   * the integrity of the transmit pbuf queue.
   *
   */
  SYS_ARCH_PROTECT(lev);

  /**
   * Bump the reference count on the pbuf to prevent it from being
   * freed till we are done with it.
   *
   */
  pbuf_ref(p);

  /**
   * If the transmitter is idle, and there is nothing on the queue,
   * send the pbuf now.
   *
   */
  if(PBUF_QUEUE_EMPTY(&stellarisif->txq) &&
    ((HWREG(ETH_BASE + MAC_O_TR) & MAC_TR_NEWTX) == 0)) {
    stellarisif_transmit(netif, p);
  }

  /* Otherwise place the pbuf on the transmit queue. */
  else {
    /* Add to transmit packet queue */
    if(!enqueue_packet(p, &(stellarisif->txq))) {
      /* if no room on the queue, free the pbuf reference and return error. */
      pbuf_free(p);
      SYS_ARCH_UNPROTECT(lev);
      return (ERR_MEM);
    }
  }

  /* Return to prior interrupt state and return. */
  SYS_ARCH_UNPROTECT(lev);
  return ERR_OK;
}
コード例 #6
0
ファイル: pbuf.c プロジェクト: liexusong/lwip-copy
/**
 * @internal only called from pbuf_alloc()
 */
static struct pbuf *
pbuf_pool_alloc(void)
{
  struct pbuf *p = NULL;

  SYS_ARCH_DECL_PROTECT(old_level);
  SYS_ARCH_PROTECT(old_level);

#if !SYS_LIGHTWEIGHT_PROT
  /* Next, check the actual pbuf pool, but if the pool is locked, we
     pretend to be out of buffers and return NULL. */
  if (pbuf_pool_free_lock) {
#if PBUF_STATS
    ++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
    return NULL;
  }
  pbuf_pool_alloc_lock = 1;
  if (!pbuf_pool_free_lock) {
#endif /* SYS_LIGHTWEIGHT_PROT */
    p = pbuf_pool;
    if (p) {
      pbuf_pool = p->next;
    }
#if !SYS_LIGHTWEIGHT_PROT
#if PBUF_STATS
  } else {
    ++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
  }
  pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */

#if PBUF_STATS
  if (p != NULL) {
    ++lwip_stats.pbuf.used;
    if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
      lwip_stats.pbuf.max = lwip_stats.pbuf.used;
    }
  }
#endif /* PBUF_STATS */

  SYS_ARCH_UNPROTECT(old_level);
  return p;
}
コード例 #7
0
ファイル: lwip_memp.c プロジェクト: NXPmicro/mbed
/**
 * Do an overflow check for all elements in every pool.
 *
 * @see memp_overflow_check_element for a description of the check
 */
static void
memp_overflow_check_all(void)
{
  u16_t i, j;
  struct memp *p;
  SYS_ARCH_DECL_PROTECT(old_level);
  SYS_ARCH_PROTECT(old_level);

  for (i = 0; i < MEMP_MAX; ++i) {
    p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base);
    for (j = 0; j < memp_pools[i]->num; ++j) {
      memp_overflow_check_element_overflow(p, memp_pools[i]);
      memp_overflow_check_element_underflow(p, memp_pools[i]);
      p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED));
    }
  }
  SYS_ARCH_UNPROTECT(old_level);
}
コード例 #8
0
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
        SYS_ARCH_DECL_PROTECT(lev);
        err_t err;
        struct xemac_s *xemac = (struct xemac_s *)(netif->state);
        xaxiemacif_s *xaxiemacif = (xaxiemacif_s *)(xemac->state);

	/*
	 * With AXI Ethernet on Zynq, we observed unexplained delays for
	 * BD Status update. As a result, we are hitting a condition where 
	 * there are no BDs free to transmit packets. So, we have added
	 * this logic where we look for the status update in a definite
	 * loop.
	 */
	XAxiDma_BdRing *txring = XAxiDma_GetTxRing(&xaxiemacif->axidma);
        int count = 100;

        SYS_ARCH_PROTECT(lev);

        while (count) {

        	/* check if space is available to send */
        	if (is_tx_space_available(xaxiemacif)) {
                	_unbuffered_low_level_output(xaxiemacif, p);
                	err = ERR_OK;
                	break;
        	} else {
#if LINK_STATS
                	lwip_stats.link.drop++;
#endif
                	process_sent_bds(txring);
                	count--;
        	}
        }

	if (count == 0) {
		print("pack dropped, no space\r\n");
		err = ERR_MEM;
	}

        SYS_ARCH_UNPROTECT(lev);
        return err;
}
コード例 #9
0
ファイル: pcapif.c プロジェクト: yarrick/lwip-contrib
static int
pcaipf_is_tx_packet(struct netif *netif, const void *packet, int packet_len)
{
  struct pcapif_private *priv = (struct pcapif_private*)PCAPIF_GET_STATE_PTR(netif);
  struct pcapipf_pending_packet *iter, *last;
  SYS_ARCH_DECL_PROTECT(lev);

  last = priv->tx_packets;
  if (last == NULL) {
    /* list is empty */
    return 0;
  }
  /* compare the first packet */
  if (pcapif_compare_packets(last, packet, packet_len)) {
    SYS_ARCH_PROTECT(lev);
    LWIP_ASSERT("list has changed", last == priv->tx_packets);
    priv->tx_packets = last->next;
    last->next = priv->free_packets;
    priv->free_packets = last;
    last->len = 0;
    SYS_ARCH_UNPROTECT(lev);
    return 1;
  }
  SYS_ARCH_PROTECT(lev);
  for (iter = last->next; iter != NULL; last = iter, iter = iter->next) {
    /* unlock while comparing (this works because we have a clean threading separation
       of adding and removing items and adding is only done at the end) */
    SYS_ARCH_UNPROTECT(lev);
    if (pcapif_compare_packets(iter, packet, packet_len)) {
      SYS_ARCH_PROTECT(lev);
      LWIP_ASSERT("last != NULL", last != NULL);
      last->next = iter->next;
      iter->next = priv->free_packets;
      priv->free_packets = iter;
      last->len = 0;
      SYS_ARCH_UNPROTECT(lev);
      return 1;
    }
    SYS_ARCH_PROTECT(lev);
  }
  SYS_ARCH_UNPROTECT(lev);
  return 0;
}
コード例 #10
0
/** Queue a call to pbuf_free_ooseq if not already queued. */
static void
pbuf_pool_is_empty(void)
{
#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
  SYS_ARCH_SET(pbuf_free_ooseq_pending, 1);
#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
  u8_t queued;
  SYS_ARCH_DECL_PROTECT(old_level);
  SYS_ARCH_PROTECT(old_level);
  queued = pbuf_free_ooseq_pending;
  pbuf_free_ooseq_pending = 1;
  SYS_ARCH_UNPROTECT(old_level);

  if (!queued) {
    /* queue a call to pbuf_free_ooseq if not already queued */
    PBUF_POOL_FREE_OOSEQ_QUEUE_CALL();
  }
#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
}
コード例 #11
0
ファイル: api_msg.c プロジェクト: 3dot3/nodemcu-firmware
/**
 * TCP callback function if a connection (opened by tcp_connect/do_connect) has
 * been established (or reset by the remote host).
 *
 * @see tcp.h (struct tcp_pcb.connected) for parameters and return values
 */
static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
  struct netconn *conn;
  int was_blocking;

  LWIP_UNUSED_ARG(pcb);

  conn = (struct netconn *)arg;

  if (conn == NULL) {
    return ERR_VAL;
  }

  LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);
  LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect",
    (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));

  if (conn->current_msg != NULL) {
    conn->current_msg->err = err;
  }
  if ((conn->type == NETCONN_TCP) && (err == ERR_OK)) {
    setup_tcp(conn);
  }
  was_blocking = !IN_NONBLOCKING_CONNECT(conn);
  SET_NONBLOCKING_CONNECT(conn, 0);
  conn->current_msg = NULL;
  conn->state = NETCONN_NONE;
  if (!was_blocking) {
    SYS_ARCH_DECL_PROTECT(lev);
    SYS_ARCH_PROTECT(lev);
    if (conn->last_err == ERR_INPROGRESS) {
      conn->last_err = ERR_OK;
    }
    SYS_ARCH_UNPROTECT(lev);
  }
  API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);

  if (was_blocking) {
    sys_sem_signal(&conn->op_completed);
  }
  return ERR_OK;
}
コード例 #12
0
ファイル: ethernetif.c プロジェクト: 003900107/wpa900-com
/**
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
err_t  ethernetif_1_input (struct netif *netif)
{
  //(void)p_arg;
  //INT8U     err;
  struct pbuf *p;
  extern struct netif netif_1;
  
  netif = &netif_1;
  
  while(1)
  {
//    OSSemPend(Eth1_pkt_Sem,0,&err);
//    printf("\n\n\r网口1数据包接收信号量");
    //ethernetif_1_input(netif);
    if(ETH_GetRxPktSize() != 0)
    {
      //ethernetif_1_input(netif);
      SYS_ARCH_DECL_PROTECT(sr);
  
      SYS_ARCH_PROTECT(sr);
      /* move received packet into a new pbuf */
      p = low_level_1_input(netif);
      SYS_ARCH_UNPROTECT(sr);
      
      if (p != NULL)
      {
        err_t err;
        err = netif->input(p, netif); // 将pbuf传递给上层协议栈
        if (err != ERR_OK)
        {
          LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
          pbuf_free(p);
          p = NULL;
        }
      }
    }
    else
    {
      OSTimeDlyHMSM(0, 0, 0, 5);
    }
  }
}
コード例 #13
0
/** Queue a call to pbuf_free_ooseq if not already queued. */
static void
pbuf_pool_is_empty(void)
{
  u8_t queued;
  SYS_ARCH_DECL_PROTECT(old_level);

  SYS_ARCH_PROTECT(old_level);
  queued = pbuf_free_ooseq_queued;
  pbuf_free_ooseq_queued = 1;
  SYS_ARCH_UNPROTECT(old_level);

  if(!queued) {
    /* queue a call to pbuf_free_ooseq if not already queued */
    if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) {
      SYS_ARCH_PROTECT(old_level);
      pbuf_free_ooseq_queued = 0;
      SYS_ARCH_UNPROTECT(old_level);
    }
  }
}
コード例 #14
0
ファイル: pbuf.c プロジェクト: AthenaYu/ESP8266_RTOS_SDK
/**
 * Attempt to reclaim some memory from queued out-of-sequence TCP segments
 * if we run out of pool pbufs. It's better to give priority to new packets
 * if we're running out.
 *
 * This must be done in the correct thread context therefore this function
 * can only be used with NO_SYS=0 and through tcpip_callback.
 */
#if !NO_SYS
//static
#endif /* !NO_SYS */
void
pbuf_free_ooseq(void)
{
  struct tcp_pcb* pcb;
  SYS_ARCH_DECL_PROTECT(old_level);

  SYS_ARCH_PROTECT(old_level);
  pbuf_free_ooseq_pending = 0;
  SYS_ARCH_UNPROTECT(old_level);

  for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
    if (NULL != pcb->ooseq) {
      /** Free the ooseq pbufs of one PCB only */
      LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
      tcp_segs_free(pcb->ooseq);
      pcb->ooseq = NULL;
      return;
    }
  }
}
コード例 #15
0
ファイル: pcapif.c プロジェクト: killvxk/lwip-allnetworks
/**
 * pcapif_init(): initialization function, pass to netif_add().
 */
err_t
pcapif_init(struct netif *netif)
{
  static int ethernetif_index;

  int local_index;
  SYS_ARCH_DECL_PROTECT(lev);
  SYS_ARCH_PROTECT(lev);
  local_index = ethernetif_index++;
  SYS_ARCH_UNPROTECT(lev);

  netif->name[0] = IFNAME0;
  netif->name[1] = (char)(IFNAME1 + local_index);
  netif->linkoutput = pcapif_low_level_output;
#if LWIP_ARP
  netif->output = etharp_output;
#if LWIP_IPV6
  netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
#else /* LWIP_ARP */
  netif->output = NULL; /* not used for PPPoE */
#if LWIP_IPV6
  netif->output_ip6 = NULL; /* not used for PPPoE */
#endif /* LWIP_IPV6 */
#endif /* LWIP_ARP */
#if LWIP_NETIF_HOSTNAME
  /* Initialize interface hostname */
  netif_set_hostname(netif, "lwip");
#endif /* LWIP_NETIF_HOSTNAME */

  netif->mtu = 1500;
  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
  netif->hwaddr_len = ETHARP_HWADDR_LEN;

  NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);

  /* sets link up or down based on current status */
  pcapif_low_level_init(netif);

  return ERR_OK;
}
コード例 #16
0
ファイル: pbuf.c プロジェクト: nodemcu/nodemcu-firmware
/**
 * Attempt to reclaim some memory from queued out-of-sequence TCP segments
 * if we run out of pool pbufs. It's better to give priority to new packets
 * if we're running out.
 *
 * This must be done in the correct thread context therefore this function
 * can only be used with NO_SYS=0 and through tcpip_callback.
 */
static void ICACHE_FLASH_ATTR
pbuf_free_ooseq(void* arg)
{
  struct tcp_pcb* pcb;
  SYS_ARCH_DECL_PROTECT(old_level);
  LWIP_UNUSED_ARG(arg);

  SYS_ARCH_PROTECT(old_level);
  pbuf_free_ooseq_queued = 0;
  SYS_ARCH_UNPROTECT(old_level);

  for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
    if (NULL != pcb->ooseq) {
      /** Free the ooseq pbufs of one PCB only */
      LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
      tcp_segs_free(pcb->ooseq);
      pcb->ooseq = NULL;
      return;
    }
  }
}
コード例 #17
0
ファイル: ethernetif.c プロジェクト: saeedhadi/Metering
/**
 * In this function, the hardware should be initialized.
 * Called from ethernetif_init().
 *
 * @param netif the already initialized lwip network interface structure
 *        for this ethernetif
 */
static void
low_level_init(struct netif *netif)
{
  CPU_INT08U  os_err;

  SYS_ARCH_DECL_PROTECT(sr);
    
  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;

  /* set MAC hardware address */
  netif->hwaddr[0] =  emacETHADDR0;
  netif->hwaddr[1] =  emacETHADDR1;
  netif->hwaddr[2] =  emacETHADDR2;
  netif->hwaddr[3] =  emacETHADDR3;
  netif->hwaddr[4] =  emacETHADDR4;
  netif->hwaddr[5] =  emacETHADDR5;

  /* maximum transfer unit */
  netif->mtu = 1500;

  /* device capabilities */
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;

  SYS_ARCH_PROTECT(sr);

  Ethernet_Initialize();

  SYS_ARCH_UNPROTECT(sr);

  os_err = OSTaskCreate( (void (*)(void *)) ethernetif_input,				
                         (void          * ) 0,							
                         (OS_STK        * )&App_Task_Ethernetif_Input_Stk[APP_TASK_ETHERNETIF_INPUT_STK_SIZE - 1],		
                         (INT8U           ) APP_TASK_ETHERNETIF_INPUT_PRIO  );							

//  #if OS_TASK_NAME_EN > 0
//  OSTaskNameSet(APP_TASK_BLINK_PRIO, "Task ethernetif_input", &os_err);
//  #endif  
}
コード例 #18
0
ファイル: sys_arch.c プロジェクト: greg100795/virtualbox
/**
 * Grab the pointer to this thread's timeouts from TLS.
 */
struct sys_timeouts *sys_arch_timeouts(void)
{
    unsigned i;
#if SYS_LIGHTWEIGHT_PROT
    SYS_ARCH_DECL_PROTECT(old_level);
#endif
    RTTHREAD myself;
    struct sys_timeouts *to = NULL;

    myself = RTThreadSelf();
#if SYS_LIGHTWEIGHT_PROT
    SYS_ARCH_PROTECT(old_level);
#else
    RTSemEventWait(g_ThreadSem, RT_INDEFINITE_WAIT);
#endif
    for (i = 0; i < g_cThreads; i++)
    {
        if (g_aTLS[i].tid == myself)
        {
            to = &g_aTLS[i].timeouts;
            break;
        }
    }
    /* Auto-adopt new threads which use lwIP as they pop up. */
    if (!to)
    {
        unsigned id;
        id = g_cThreads;
        g_cThreads++;
        Assert(g_cThreads <= THREADS_MAX);
        g_aTLS[id].tid = myself;
        to = &g_aTLS[id].timeouts;
    }
#if SYS_LIGHTWEIGHT_PROT
    SYS_ARCH_UNPROTECT(old_level);
#else
    RTSemEventSignal(g_ThreadSem);
#endif
    return to;
}
コード例 #19
0
ファイル: pbuf.c プロジェクト: mohankku/aos_project
/**
 * Attempt to reclaim some memory from queued out-of-sequence TCP segments
 * if we run out of pool pbufs. It's better to give priority to new packets
 * if we're running out.
 *
 * This must be done in the correct thread context therefore this function
 * can only be used with NO_SYS=0 and through tcpip_callback.
 */
static void
pbuf_free_ooseq(void* arg)
{
  struct tcp_pcb* pcb;
  char cpu = sched_getcpu();
  SYS_ARCH_DECL_PROTECT(old_level);
  LWIP_UNUSED_ARG(arg);

  SYS_ARCH_PROTECT(old_level);
  pbuf_free_ooseq_queued = 0;
  SYS_ARCH_UNPROTECT(old_level);

  for (pcb = lwip_tcpip_thread[cpu]->tcpip_data.tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
    if (NULL != pcb->ooseq) {
      /** Free the ooseq pbufs of one PCB only */
      LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free_ooseq: freeing out-of-sequence pbufs\n"));
      tcp_segs_free(pcb->ooseq);
      pcb->ooseq = NULL;
      return;
    }
  }
}
コード例 #20
0
ファイル: sys_arch.c プロジェクト: wenjiapeng/lwip
void sys_mbox_post(sys_mbox_t q, void *msg)
{
  DWORD ret;
  SYS_ARCH_DECL_PROTECT(lev);

  /* parameter check */
  LWIP_ASSERT("sys_mbox_free ", q != SYS_MBOX_NULL );
  LWIP_ASSERT("q->sem != NULL", q->sem != NULL);
  LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE);

  SYS_ARCH_PROTECT(lev);
  q->q_mem[q->head] = msg;
  (q->head)++;
  if (q->head >= MAX_QUEUE_ENTRIES) {
    q->head = 0;
  }
  LWIP_ASSERT("mbox is full!", q->head != q->tail);
  ret = ReleaseSemaphore(q->sem, 1, 0);
  LWIP_ASSERT("Error releasing sem", ret != 0);

  SYS_ARCH_UNPROTECT(lev);
}
コード例 #21
0
ファイル: sys_arch.c プロジェクト: wenjiapeng/lwip
u32_t sys_arch_mbox_fetch(sys_mbox_t q, void **msg, u32_t timeout)
{
  DWORD ret;
  LONGLONG starttime, endtime;
  SYS_ARCH_DECL_PROTECT(lev);

  /* parameter check */
  LWIP_ASSERT("sys_mbox_free ", q != SYS_MBOX_NULL );
  LWIP_ASSERT("q->sem != NULL", q->sem != NULL);
  LWIP_ASSERT("q->sem != INVALID_HANDLE_VALUE", q->sem != INVALID_HANDLE_VALUE);

  if (timeout == 0) {
    timeout = INFINITE;
  }
  starttime = sys_get_ms_longlong();
  if ((ret = WaitForSingleObject(q->sem, timeout)) == WAIT_OBJECT_0) {
    SYS_ARCH_PROTECT(lev);
    if(msg != NULL) {
      *msg  = q->q_mem[q->tail];
    }

    (q->tail)++;
    if (q->tail >= MAX_QUEUE_ENTRIES) {
      q->tail = 0;
    }
    SYS_ARCH_UNPROTECT(lev);
    endtime = sys_get_ms_longlong();
    return (u32_t)(endtime - starttime);
  }
  else
  {
    LWIP_ASSERT("Error waiting for sem", ret == WAIT_TIMEOUT);
    if(msg != NULL) {
      *msg  = NULL;
    }

    return SYS_ARCH_TIMEOUT;
  }
}
コード例 #22
0
ファイル: lwip_drv.cpp プロジェクト: bratkov/tmos
/**
 * Push a pbuf packet onto a pbuf packet queue
 *
 * @param p is the pbuf to push onto the packet queue.
 * @param q is the packet queue.
 *
 * @return 1 if successful, 0 if q is full.
 */
static int enqueue_packet(struct pbuf *p, struct pbufq *q)
{
	SYS_ARCH_DECL_PROTECT(lev);
	int ret;

	/**
	 * This entire function must run within a "critical section" to preserve
	 * the integrity of the transmit pbuf queue.
	 *
	 */
	SYS_ARCH_PROTECT(lev);

	if (!PBUF_QUEUE_FULL(q))
	{
		/**
		 * The queue isn't full so we add the new frame at the current
		 * write position and move the write pointer.
		 *
		 */
		q->pbuf[q->qwrite] = p;
		q->qwrite = ((q->qwrite + 1) % STELLARIS_NUM_PBUF_QUEUE);
		ret = 1;
	}
	else
	{
		/**
		 * The stack is full so we are throwing away this value.  Keep track
		 * of the number of times this happens.
		 *
		 */
		q->overflow++;
		ret = 0;
	}

	/* Return to prior interrupt state and return the pbuf pointer. */
	SYS_ARCH_UNPROTECT(lev);
	return (ret);
}
コード例 #23
0
ファイル: ethernetif.c プロジェクト: saeedhadi/Metering
static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
  struct pbuf *q;
  int len = 0;

  SYS_ARCH_DECL_PROTECT(sr);
  /* Interrupts are disabled through this whole thing to support multi-threading
	   transmit calls. Also this function might be called from an ISR. */
  SYS_ARCH_PROTECT(sr);

  for(q = p; q != NULL; q = q->next) 
  {
    memcpy((u8_t*)&gTxBuf[len], q->payload, q->len);
	len = len + q->len;
  }

  SendFrame(gTxBuf, len);

  SYS_ARCH_UNPROTECT(sr);

  return ERR_OK;
}
コード例 #24
0
ファイル: sys_arch.c プロジェクト: AndreyMostovov/asf
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
{
  sys_thread_t    newthread;
  portBASE_TYPE   result;
  SYS_ARCH_DECL_PROTECT(protectionLevel);

  result = xTaskCreate( thread, (signed portCHAR *)name, stacksize, arg, prio, &newthread );

  // Need to protect this -- preemption here could be a problem!
  SYS_ARCH_PROTECT(protectionLevel);
  if( pdPASS == result )
  {
    // For each task created, store the task handle (pid) in the timers array.
    // This scheme doesn't allow for threads to be deleted
    Threads_TimeoutsList[NbActiveThreads++].pid = newthread;
  }
  else
  {
    newthread = NULL;
  }
  SYS_ARCH_UNPROTECT(protectionLevel);

  return( newthread );
}
void
memp_free(memp_t type, void *mem)
{
  struct memp *memp;
#if SYS_LIGHTWEIGHT_PROT
  SYS_ARCH_DECL_PROTECT(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */  

  if (mem == NULL) {
    return;
  }
  memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));

#if SYS_LIGHTWEIGHT_PROT
    SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */  
  sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */  

#if MEMP_STATS
  lwip_stats.memp[type].used--; 
#endif /* MEMP_STATS */
  
  memp->next = memp_tab[type]; 
  memp_tab[type] = memp;

#if MEMP_SANITY_CHECK
  LWIP_ASSERT("memp sanity", memp_sanity());
#endif  

#if SYS_LIGHTWEIGHT_PROT
  SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
  sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */  
}
コード例 #26
0
ファイル: sys_arch.c プロジェクト: ChenZewei/acoral
/********************************************
* 函数名称 : sys_arch_timeouts
* 描    述 : 获得线程的超时结构
* 输 	 入 : 无
*        
* 输 	 出 : struct sys_timeouts *: 线程的超时结构
********************************************/
struct sys_timeouts * sys_arch_timeouts(void)
{
    struct timeoutnode * pto = timeoutslist;
   	u8_t curprio;	    
	SYS_ARCH_DECL_PROTECT(cpusr);

	SYS_ARCH_PROTECT(cpusr);
	curprio = acoral_cur_thread->prio;
    SYS_ARCH_UNPROTECT(cpusr);
           	    
    while (pto != &nulltimeouts)
    {
    	if (pto->prio == curprio)
    	{
    		return &(pto->timeouts);
    	}
    	else
    	{
    		pto = pto->next;
    	}
    }

    return &(pto->timeouts);
}
コード例 #27
0
ファイル: sys_arch.c プロジェクト: greg100795/virtualbox
/**
 * Create new thread.
 */
sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)
{
    int rc;
#if SYS_LIGHTWEIGHT_PROT
    SYS_ARCH_DECL_PROTECT(old_level);
#endif
    unsigned id;
    RTTHREAD tid;

#if SYS_LIGHTWEIGHT_PROT
    SYS_ARCH_PROTECT(old_level);
#else
    RTSemEventWait(g_ThreadSem, RT_INDEFINITE_WAIT);
#endif
    id = g_cThreads;
    g_cThreads++;
    Assert(g_cThreads <= THREADS_MAX);
    g_aTLS[id].thread = thread;
    g_aTLS[id].arg = arg;
    rc = RTThreadCreateF(&tid, sys_thread_adapter, &g_aTLS[id], 0,
                         RTTHREADTYPE_IO, 0, "lwIP%u", id);
    if (RT_FAILURE(rc))
    {
        g_cThreads--;
        tid = NIL_RTTHREAD;
    }
    else
        g_aTLS[id].tid = tid;
#if SYS_LIGHTWEIGHT_PROT
    SYS_ARCH_UNPROTECT(old_level);
#else
    RTSemEventSignal(g_ThreadSem);
#endif
    AssertRC(rc);
    return tid;
}
コード例 #28
0
ファイル: xadapter.c プロジェクト: AlexShiLucky/freertos
int
xemacif_input(struct netif *netif)
{
	struct xemac_s *emac = (struct xemac_s *)netif->state;
	SYS_ARCH_DECL_PROTECT(lev);

	int n_packets = 0;

	switch (emac->type) {
		case xemac_type_xps_emaclite:
#ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
			SYS_ARCH_PROTECT(lev);
			n_packets = xemacliteif_input(netif);
			SYS_ARCH_UNPROTECT(lev);
			break;
#else
			print("incorrect configuration: xps_ethernetlite drivers not present?");
			while(1);
			return 0;
#endif
		case xemac_type_xps_ll_temac:
#ifdef XLWIP_CONFIG_INCLUDE_TEMAC
			SYS_ARCH_PROTECT(lev);
			n_packets = xlltemacif_input(netif);
			SYS_ARCH_UNPROTECT(lev);
			break;
#else
			print("incorrect configuration: xps_ll_temac drivers not present?");
			while(1);
			return 0;
#endif
		case xemac_type_axi_ethernet:
#ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
			SYS_ARCH_PROTECT(lev);
			n_packets = xaxiemacif_input(netif);
			SYS_ARCH_UNPROTECT(lev);
			break;
#else
			print("incorrect configuration: axi_ethernet drivers not present?");
			while(1);
			return 0;
#endif
#ifdef __arm__
		case xemac_type_emacps:
#ifdef XLWIP_CONFIG_INCLUDE_GEM
			SYS_ARCH_PROTECT(lev);
			n_packets = xemacpsif_input(netif);
			SYS_ARCH_UNPROTECT(lev);
			break;
#else
			xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n");
			while(1);
			return 0;
#endif
#endif
		default:
			print("incorrect configuration: unknown temac type");
			while(1);
			return 0;
	}

	return n_packets;
}
コード例 #29
0
ファイル: api_msg.c プロジェクト: comrid1987/jb3500
/**
 * Receive callback function for UDP netconns.
 * Posts the packet to conn->recvmbox or deletes it on memory error.
 *
 * @see udp.h (struct udp_pcb.recv) for parameters
 */
static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
         ip_addr_t *addr, u16_t port)
{
    struct netbuf *buf;
    struct netconn *conn;
    u16_t len;
#if LWIP_SO_RCVBUF
    int recv_avail;
#endif /* LWIP_SO_RCVBUF */

    LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
    LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
    LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
    conn = (struct netconn *)arg;
    LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);

#if LWIP_SO_RCVBUF
    SYS_ARCH_GET(conn->recv_avail, recv_avail);
    if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
            ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
#else  /* LWIP_SO_RCVBUF */
    if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
#endif /* LWIP_SO_RCVBUF */
        pbuf_free(p);
        return;
    }

    buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
    if (buf == NULL) {
        pbuf_free(p);
        return;
    } else {
        buf->p = p;
        buf->ptr = p;
        ip_addr_set(&buf->addr, addr);
        buf->port = port;
#if LWIP_NETBUF_RECVINFO
        {
            const struct ip_hdr* iphdr = ip_current_header();
            /* get the UDP header - always in the first pbuf, ensured by udp_input */
            const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
#if LWIP_CHECKSUM_ON_COPY
            buf->flags = NETBUF_FLAG_DESTADDR;
#endif /* LWIP_CHECKSUM_ON_COPY */
            ip_addr_set(&buf->toaddr, ip_current_dest_addr());
            buf->toport_chksum = udphdr->dest;
        }
#endif /* LWIP_NETBUF_RECVINFO */
    }

    len = p->tot_len;
    if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
        netbuf_delete(buf);
        return;
    } else {
#if LWIP_SO_RCVBUF
        SYS_ARCH_INC(conn->recv_avail, len);
#endif /* LWIP_SO_RCVBUF */
        /* Register event with callback */
        API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
    }
}
#endif /* LWIP_UDP */

#if LWIP_TCP
/**
 * Receive callback function for TCP netconns.
 * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
 *
 * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
 */
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
    struct netconn *conn;
    u16_t len;

    LWIP_UNUSED_ARG(pcb);
    LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
    LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
    conn = (struct netconn *)arg;
    LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);

    if (conn == NULL) {
        return ERR_VAL;
    }
    if (!sys_mbox_valid(&conn->recvmbox)) {
        /* recvmbox already deleted */
        if (p != NULL) {
            tcp_recved(pcb, p->tot_len);
            pbuf_free(p);
        }
        return ERR_OK;
    }
    /* Unlike for UDP or RAW pcbs, don't check for available space
       using recv_avail since that could break the connection
       (data is already ACKed) */

    /* don't overwrite fatal errors! */
    NETCONN_SET_SAFE_ERR(conn, err);

    if (p != NULL) {
        len = p->tot_len;
    } else {
        len = 0;
    }

    if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) {
        /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
        return ERR_MEM;
    } else {
#if LWIP_SO_RCVBUF
        SYS_ARCH_INC(conn->recv_avail, len);
#endif /* LWIP_SO_RCVBUF */
        /* Register event with callback */
        API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
    }

    return ERR_OK;
}

/**
 * Poll callback function for TCP netconns.
 * Wakes up an application thread that waits for a connection to close
 * or data to be sent. The application thread then takes the
 * appropriate action to go on.
 *
 * Signals the conn->sem.
 * netconn_close waits for conn->sem if closing failed.
 *
 * @see tcp.h (struct tcp_pcb.poll) for parameters and return value
 */
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
    struct netconn *conn = (struct netconn *)arg;

    LWIP_UNUSED_ARG(pcb);
    LWIP_ASSERT("conn != NULL", (conn != NULL));

    if (conn->state == NETCONN_WRITE) {
        do_writemore(conn);
    } else if (conn->state == NETCONN_CLOSE) {
        do_close_internal(conn);
    }
    /* @todo: implement connect timeout here? */

    /* Did a nonblocking write fail before? Then check available write-space. */
    if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
        /* If the queued byte- or pbuf-count drops below the configured low-water limit,
           let select mark this pcb as writable again. */
        if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
                (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
            conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
            API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
        }
    }

    return ERR_OK;
}

/**
 * Sent callback function for TCP netconns.
 * Signals the conn->sem and calls API_EVENT.
 * netconn_write waits for conn->sem if send buffer is low.
 *
 * @see tcp.h (struct tcp_pcb.sent) for parameters and return value
 */
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
    struct netconn *conn = (struct netconn *)arg;

    LWIP_UNUSED_ARG(pcb);
    LWIP_ASSERT("conn != NULL", (conn != NULL));

    if (conn->state == NETCONN_WRITE) {
        do_writemore(conn);
    } else if (conn->state == NETCONN_CLOSE) {
        do_close_internal(conn);
    }

    if (conn) {
        /* If the queued byte- or pbuf-count drops below the configured low-water limit,
           let select mark this pcb as writable again. */
        if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
                (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
            conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
            API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
        }
    }

    return ERR_OK;
}

/**
 * Error callback function for TCP netconns.
 * Signals conn->sem, posts to all conn mboxes and calls API_EVENT.
 * The application thread has then to decide what to do.
 *
 * @see tcp.h (struct tcp_pcb.err) for parameters
 */
static void
err_tcp(void *arg, err_t err)
{
    struct netconn *conn;
    enum netconn_state old_state;
    SYS_ARCH_DECL_PROTECT(lev);

    conn = (struct netconn *)arg;
    LWIP_ASSERT("conn != NULL", (conn != NULL));

    conn->pcb.tcp = NULL;

    /* no check since this is always fatal! */
    SYS_ARCH_PROTECT(lev);
    conn->last_err = err;
    SYS_ARCH_UNPROTECT(lev);

    /* reset conn->state now before waking up other threads */
    old_state = conn->state;
    conn->state = NETCONN_NONE;

    /* Notify the user layer about a connection error. Used to signal
       select. */
    API_EVENT(conn, NETCONN_EVT_ERROR, 0);
    /* Try to release selects pending on 'read' or 'write', too.
       They will get an error if they actually try to read or write. */
    API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
    API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);

    /* pass NULL-message to recvmbox to wake up pending recv */
    if (sys_mbox_valid(&conn->recvmbox)) {
        /* use trypost to prevent deadlock */
        sys_mbox_trypost(&conn->recvmbox, NULL);
    }
    /* pass NULL-message to acceptmbox to wake up pending accept */
    if (sys_mbox_valid(&conn->acceptmbox)) {
        /* use trypost to preven deadlock */
        sys_mbox_trypost(&conn->acceptmbox, NULL);
    }

    if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
            (old_state == NETCONN_CONNECT)) {
        /* calling do_writemore/do_close_internal is not necessary
           since the pcb has already been deleted! */
        int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
        SET_NONBLOCKING_CONNECT(conn, 0);

        if (!was_nonblocking_connect) {
            /* set error return code */
            LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
            conn->current_msg->err = err;
            conn->current_msg = NULL;
            /* wake up the waiting task */
            sys_sem_signal(&conn->op_completed);
        }
    } else {
        LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL);
    }
}

/**
 * Setup a tcp_pcb with the correct callback function pointers
 * and their arguments.
 *
 * @param conn the TCP netconn to setup
 */
static void
setup_tcp(struct netconn *conn)
{
    struct tcp_pcb *pcb;

    pcb = conn->pcb.tcp;
    tcp_arg(pcb, conn);
    tcp_recv(pcb, recv_tcp);
    tcp_sent(pcb, sent_tcp);
    tcp_poll(pcb, poll_tcp, 4);
    tcp_err(pcb, err_tcp);
}

/**
 * Accept callback function for TCP netconns.
 * Allocates a new netconn and posts that to conn->acceptmbox.
 *
 * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
 */
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    struct netconn *newconn;
    struct netconn *conn = (struct netconn *)arg;

    LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));

    if (!sys_mbox_valid(&conn->acceptmbox)) {
        LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n"));
        return ERR_VAL;
    }

    /* We have to set the callback here even though
     * the new socket is unknown. conn->socket is marked as -1. */
    newconn = netconn_alloc(conn->type, conn->callback);
    if (newconn == NULL) {
        return ERR_MEM;
    }
    newconn->pcb.tcp = newpcb;
    setup_tcp(newconn);
    /* no protection: when creating the pcb, the netconn is not yet known
       to the application thread */
    newconn->last_err = err;

    if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
        /* When returning != ERR_OK, the pcb is aborted in tcp_process(),
           so do nothing here! */
        /* remove all references to this netconn from the pcb */
        struct tcp_pcb* pcb = newconn->pcb.tcp;
        tcp_arg(pcb, NULL);
        tcp_recv(pcb, NULL);
        tcp_sent(pcb, NULL);
        tcp_poll(pcb, NULL, 4);
        tcp_err(pcb, NULL);
        /* remove reference from to the pcb from this netconn */
        newconn->pcb.tcp = NULL;
        /* no need to drain since we know the recvmbox is empty. */
        sys_mbox_free(&newconn->recvmbox);
        sys_mbox_set_invalid(&newconn->recvmbox);
        netconn_free(newconn);
        return ERR_MEM;
    } else {
        /* Register event with callback */
        API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
    }

    return ERR_OK;
}
#endif /* LWIP_TCP */

/**
 * Create a new pcb of a specific type.
 * Called from do_newconn().
 *
 * @param msg the api_msg_msg describing the connection type
 * @return msg->conn->err, but the return value is currently ignored
 */
static void
pcb_new(struct api_msg_msg *msg)
{
    LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);

    /* Allocate a PCB for this connection */
    switch(NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
    case NETCONN_RAW:
        msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
        if(msg->conn->pcb.raw == NULL) {
            msg->err = ERR_MEM;
            break;
        }
        raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
        break;
#endif /* LWIP_RAW */
#if LWIP_UDP
    case NETCONN_UDP:
        msg->conn->pcb.udp = udp_new();
        if(msg->conn->pcb.udp == NULL) {
            msg->err = ERR_MEM;
            break;
        }
#if LWIP_UDPLITE
        if (msg->conn->type==NETCONN_UDPLITE) {
            udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
        }
#endif /* LWIP_UDPLITE */
        if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
            udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
        }
        udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
        break;
#endif /* LWIP_UDP */
#if LWIP_TCP
    case NETCONN_TCP:
        msg->conn->pcb.tcp = tcp_new();
        if(msg->conn->pcb.tcp == NULL) {
            msg->err = ERR_MEM;
            break;
        }
        setup_tcp(msg->conn);
        break;
#endif /* LWIP_TCP */
    default:
        /* Unsupported netconn type, e.g. protocol disabled */
        msg->err = ERR_VAL;
        break;
    }
}
コード例 #30
0
ファイル: mem.c プロジェクト: networkextension/A.BIG.T
/**
 * Shrink memory returned by mem_malloc().
 *
 * @param rmem pointer to memory allocated by mem_malloc the is to be shrinked
 * @param newsize required size after shrinking (needs to be smaller than or
 *                equal to the previous size)
 * @return for compatibility reasons: is always == rmem, at the moment
 *         or NULL if newsize is > old size, in which case rmem is NOT touched
 *         or freed!
 */
void *
mem_trim(void *rmem, mem_size_t newsize)
{
  mem_size_t size;
  mem_size_t ptr, ptr2;
  struct mem *mem, *mem2;
  /* use the FREE_PROTECT here: it protects with sem OR SYS_ARCH_PROTECT */
  LWIP_MEM_FREE_DECL_PROTECT();

  /* Expand the size of the allocated memory region so that we can
     adjust for alignment. */
  newsize = LWIP_MEM_ALIGN_SIZE(newsize);

  if(newsize < MIN_SIZE_ALIGNED) {
    /* every data block must be at least MIN_SIZE_ALIGNED long */
    newsize = MIN_SIZE_ALIGNED;
  }

  if (newsize > MEM_SIZE_ALIGNED) {
    return NULL;
  }

  LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
   (u8_t *)rmem < (u8_t *)ram_end);

  if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
    SYS_ARCH_DECL_PROTECT(lev);
    LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
    /* protect mem stats from concurrent access */
    SYS_ARCH_PROTECT(lev);
    MEM_STATS_INC(illegal);
    SYS_ARCH_UNPROTECT(lev);
    return rmem;
  }
  /* Get the corresponding struct mem ... */
  mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
  /* ... and its offset pointer */
  ptr = (mem_size_t)((u8_t *)mem - ram);

  size = mem->next - ptr - SIZEOF_STRUCT_MEM;
  LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
  if (newsize > size) {
    /* not supported */
    return NULL;
  }
  if (newsize == size) {
    /* No change in size, simply return */
    return rmem;
  }

  /* protect the heap from concurrent access */
  LWIP_MEM_FREE_PROTECT();

  mem2 = (struct mem *)(void *)&ram[mem->next];
  if(mem2->used == 0) {
    /* The next struct is unused, we can simply move it at little */
    mem_size_t next;
    /* remember the old next pointer */
    next = mem2->next;
    /* create new struct mem which is moved directly after the shrinked mem */
    ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
    if (lfree == mem2) {
      lfree = (struct mem *)(void *)&ram[ptr2];
    }
    mem2 = (struct mem *)(void *)&ram[ptr2];
    mem2->used = 0;
    /* restore the next pointer */
    mem2->next = next;
    /* link it back to mem */
    mem2->prev = ptr;
    /* link mem to it */
    mem->next = ptr2;
    /* last thing to restore linked list: as we have moved mem2,
     * let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
     * the end of the heap */
    if (mem2->next != MEM_SIZE_ALIGNED) {
      ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
    }
    MEM_STATS_DEC_USED(used, (size - newsize));
    /* no need to plug holes, we've already done that */
  } else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
    /* Next struct is used but there's room for another struct mem with
     * at least MIN_SIZE_ALIGNED of data.
     * Old size ('size') must be big enough to contain at least 'newsize' plus a struct mem
     * ('SIZEOF_STRUCT_MEM') with some data ('MIN_SIZE_ALIGNED').
     * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
     *       region that couldn't hold data, but when mem->next gets freed,
     *       the 2 regions would be combined, resulting in more free memory */
    ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
    mem2 = (struct mem *)(void *)&ram[ptr2];
    if (mem2 < lfree) {
      lfree = mem2;
    }
    mem2->used = 0;
    mem2->next = mem->next;
    mem2->prev = ptr;
    mem->next = ptr2;
    if (mem2->next != MEM_SIZE_ALIGNED) {
      ((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
    }
    MEM_STATS_DEC_USED(used, (size - newsize));
    /* the original mem->next is used, so no need to plug holes! */
  }
  /* else {
    next struct mem is used but size between mem and mem2 is not big enough
    to create another struct mem
    -> don't do anyhting. 
    -> the remaining space stays unused since it is too small
  } */
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
  mem_free_count = 1;
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
  LWIP_MEM_FREE_UNPROTECT();
  return rmem;
}