コード例 #1
0
ファイル: l2cap.c プロジェクト: cyysu/AliOS-Things
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch,
					     struct net_buf *buf,
					     size_t sdu_hdr_len)
{
	struct net_buf *seg;
	uint16_t headroom;
	uint16_t len;

	/* Segment if data (+ data headroom) is bigger than MPS */
	if (buf->len + sdu_hdr_len > ch->tx.mps) {
		goto segment;
	}

	/* Segment if there is no space in the user_data */
	if (buf->pool->user_data_size < BT_BUF_USER_DATA_MIN) {
		BT_WARN("Too small buffer user_data_size %u",
			buf->pool->user_data_size);
		goto segment;
	}

	headroom = sizeof(struct bt_hci_acl_hdr) +
		   sizeof(struct bt_l2cap_hdr) + sdu_hdr_len;

	/* Check if original buffer has enough headroom and don't have any
	 * fragments.
	 */
	if (net_buf_headroom(buf) >= headroom && !buf->frags) {
		if (sdu_hdr_len) {
			/* Push SDU length if set */
			net_buf_push_le16(buf, net_buf_frags_len(buf));
		}
		return net_buf_ref(buf);
	}

segment:
	seg = bt_l2cap_create_pdu(&le_data_pool, 0);

	if (sdu_hdr_len) {
		net_buf_add_le16(seg, net_buf_frags_len(buf));
	}

	/* Don't send more that TX MPS including SDU length */
	len = min(net_buf_tailroom(seg), ch->tx.mps - sdu_hdr_len);
	/* Limit if original buffer is smaller than the segment */
	len = min(buf->len, len);
	net_buf_add_mem(seg, buf->data, len);
	net_buf_pull(buf, len);

	BT_DBG("ch %p seg %p len %u", ch, seg, seg->len);

	return seg;
}
コード例 #2
0
ファイル: dhcpv4.c プロジェクト: sunkaizhu/zephyr
/* Setup IPv4 + UDP header */
static void setup_header(struct net_buf *buf)
{
	struct net_ipv4_hdr *ipv4;
	struct net_udp_hdr *udp;
	uint16_t len;

	ipv4 = NET_IPV4_BUF(buf);
	udp = NET_UDP_BUF(buf);

	len = net_buf_frags_len(buf->frags);

	/* Setup IPv4 header */
	memset(ipv4, 0, sizeof(struct net_ipv4_hdr));

	ipv4->vhl = 0x45;
	ipv4->ttl = 0xFF;
	ipv4->proto = IPPROTO_UDP;
	ipv4->len[0] = len >> 8;
	ipv4->len[1] = (uint8_t)len;
	ipv4->chksum = ~net_calc_chksum_ipv4(buf);

	net_ipaddr_copy(&ipv4->dst, net_ipv4_broadcast_address());

	len -= NET_IPV4H_LEN;
	/* Setup UDP header */
	udp->src_port = htons(DHCPV4_CLIENT_PORT);
	udp->dst_port = htons(DHCPV4_SERVER_PORT);
	udp->len = htons(len);
	udp->chksum = ~net_calc_chksum_udp(buf);
}
コード例 #3
0
ファイル: bluetooth.c プロジェクト: sunkaizhu/zephyr
static enum net_verdict net_bt_recv(struct net_if *iface, struct net_buf *buf)
{
	uint32_t src;
	uint32_t dst;

	NET_DBG("iface %p buf %p len %u", iface, buf, net_buf_frags_len(buf));

	/* Uncompress will drop the current fragment. Buf ll src/dst address
	 * will then be wrong and must be updated according to the new fragment.
	 */
	src = net_nbuf_ll_src(buf)->addr ?
		net_nbuf_ll_src(buf)->addr - net_nbuf_ll(buf) : 0;
	dst = net_nbuf_ll_dst(buf)->addr ?
		net_nbuf_ll_dst(buf)->addr - net_nbuf_ll(buf) : 0;

	if (!net_6lo_uncompress(buf)) {
		NET_DBG("Packet decompression failed");
		return NET_DROP;
	}

	net_nbuf_ll_src(buf)->addr = src ? net_nbuf_ll(buf) + src : NULL;
	net_nbuf_ll_dst(buf)->addr = dst ? net_nbuf_ll(buf) + dst : NULL;

	return NET_CONTINUE;
}
コード例 #4
0
ファイル: bluetooth.c プロジェクト: sunkaizhu/zephyr
static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
	struct bt_context *ctxt = CHAN_CTXT(chan);
	struct net_buf *nbuf;

	NET_DBG("Incoming data channel %p len %u", chan,
		net_buf_frags_len(buf));

	/* Get buffer for bearer / protocol related data */
	nbuf = net_nbuf_get_reserve_rx(0);

	/* Set destination address */
	net_nbuf_ll_dst(nbuf)->addr = ctxt->src.val;
	net_nbuf_ll_dst(nbuf)->len = sizeof(ctxt->src);

	/* Set source address */
	net_nbuf_ll_src(nbuf)->addr = ctxt->dst.val;
	net_nbuf_ll_src(nbuf)->len = sizeof(ctxt->dst);

	/* Add data buffer as fragment of RX buffer, take a reference while
	 * doing so since L2CAP will unref the buffer after return.
	 */
	net_buf_frag_add(nbuf, net_buf_ref(buf));

	if (net_recv_data(ctxt->iface, nbuf) < 0) {
		NET_DBG("Packet dropped by NET stack");
		net_nbuf_unref(nbuf);
	}
}
コード例 #5
0
ファイル: bluetooth.c プロジェクト: bboozzoo/zephyr
static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
	struct bt_context *ctxt = CHAN_CTXT(chan);
	struct net_pkt *pkt;

	NET_DBG("Incoming data channel %p len %zu", chan,
		net_buf_frags_len(buf));

	/* Get packet for bearer / protocol related data */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);

	/* Set destination address */
	net_pkt_ll_dst(pkt)->addr = ctxt->src.val;
	net_pkt_ll_dst(pkt)->len = sizeof(ctxt->src);
	net_pkt_ll_dst(pkt)->type = NET_LINK_BLUETOOTH;

	/* Set source address */
	net_pkt_ll_src(pkt)->addr = ctxt->dst.val;
	net_pkt_ll_src(pkt)->len = sizeof(ctxt->dst);
	net_pkt_ll_src(pkt)->type = NET_LINK_BLUETOOTH;

	/* Add data buffer as fragment of RX buffer, take a reference while
	 * doing so since L2CAP will unref the buffer after return.
	 */
	net_pkt_frag_add(pkt, net_buf_ref(buf));

	if (net_recv_data(ctxt->iface, pkt) < 0) {
		NET_DBG("Packet dropped by NET stack");
		net_pkt_unref(pkt);
	}
}
コード例 #6
0
ファイル: l2cap.c プロジェクト: cyysu/AliOS-Things
static void l2cap_chan_le_recv_sdu(struct bt_l2cap_le_chan *chan,
				   struct net_buf *buf)
{
	struct net_buf *frag;
	uint16_t len;

	BT_DBG("chan %p len %u sdu %zu", chan, buf->len,
	       net_buf_frags_len(chan->_sdu));

	if (net_buf_frags_len(chan->_sdu) + buf->len > chan->_sdu_len) {
		BT_ERR("SDU length mismatch");
		bt_l2cap_chan_disconnect(&chan->chan);
		return;
	}

	/* Jump to last fragment */
	frag = net_buf_frag_last(chan->_sdu);

	while (buf->len) {
		/* Check if there is any space left in the current fragment */
		if (!net_buf_tailroom(frag)) {
			frag = l2cap_alloc_frag(chan);
			if (!frag) {
				BT_ERR("Unable to store SDU");
				bt_l2cap_chan_disconnect(&chan->chan);
				return;
			}
		}

		len = min(net_buf_tailroom(frag), buf->len);
		net_buf_add_mem(frag, buf->data, len);
		net_buf_pull(buf, len);

		BT_DBG("frag %p len %u", frag, frag->len);
	}

	if (net_buf_frags_len(chan->_sdu) == chan->_sdu_len) {
		/* Receiving complete SDU, notify channel and reset SDU buf */
		chan->chan.ops->recv(&chan->chan, chan->_sdu);
		net_buf_unref(chan->_sdu);
		chan->_sdu = NULL;
		chan->_sdu_len = 0;
	}

	l2cap_chan_update_credits(chan);
}
コード例 #7
0
ファイル: l2cap.c プロジェクト: cyysu/AliOS-Things
static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch,
				  struct net_buf *buf, int sent)
{
	int ret, total_len;
	struct net_buf *frag;

	total_len = net_buf_frags_len(buf) + sent;

	if (total_len > ch->tx.mtu) {
		return -EMSGSIZE;
	}

	frag = buf;
	if (!frag->len && frag->frags) {
		frag = frag->frags;
	}

	if (!sent) {
		/* Add SDU length for the first segment */
		sent = l2cap_chan_le_send(ch, frag, BT_L2CAP_SDU_HDR_LEN);
		if (sent < 0) {
			if (sent == -EAGAIN) {
				sent = 0;
				/* Store sent data into user_data */
				memcpy(net_buf_user_data(buf), &sent,
				       sizeof(sent));
			}
			return sent;
		}
	}

	/* Send remaining segments */
	for (ret = 0; sent < total_len; sent += ret) {
		/* Proceed to next fragment */
		if (!frag->len) {
			frag = net_buf_frag_del(buf, frag);
		}

		ret = l2cap_chan_le_send(ch, frag, 0);
		if (ret < 0) {
			if (ret == -EAGAIN) {
				/* Store sent data into user_data */
				memcpy(net_buf_user_data(buf), &sent,
				       sizeof(sent));
			}
			return ret;
		}
	}

	BT_DBG("ch %p cid 0x%04x sent %u", ch, ch->tx.cid, sent);

	net_buf_unref(buf);

	return ret;
}
コード例 #8
0
ファイル: wpanusb.c プロジェクト: sunkaizhu/zephyr
int net_recv_data(struct net_if *iface, struct net_buf *buf)
{
	struct net_buf *frag;

	SYS_LOG_DBG("Got data, buf %p, len %d frags->len %d",
		    buf, buf->len, net_buf_frags_len(buf));

	frag = net_buf_frag_last(buf);

	/**
	 * Add length 1 byte, do not forget to reserve it
	 */
	net_buf_push_u8(frag, net_buf_frags_len(buf) - 1);

	hexdump("<", frag->data, net_buf_frags_len(buf));

	try_write(WPANUSB_ENDP_BULK_IN, frag->data, net_buf_frags_len(buf));

	net_nbuf_unref(buf);

	return 0;
}
コード例 #9
0
ファイル: bluetooth.c プロジェクト: sunkaizhu/zephyr
static int bt_iface_send(struct net_if *iface, struct net_buf *buf)
{
	struct bt_context *ctxt = net_if_get_device(iface)->driver_data;
	int ret;

	NET_DBG("iface %p buf %p len %u", iface, buf, net_buf_frags_len(buf));

	ret = bt_l2cap_chan_send(&ctxt->ipsp_chan.chan, buf);
	if (ret < 0) {
		return ret;
	}

	return ret;
}
コード例 #10
0
ファイル: bluetooth.c プロジェクト: sunkaizhu/zephyr
static enum net_verdict net_bt_send(struct net_if *iface, struct net_buf *buf)
{
	struct bt_context *ctxt = net_if_get_device(iface)->driver_data;

	NET_DBG("iface %p buf %p len %u", iface, buf, net_buf_frags_len(buf));

	/* Only accept IPv6 packets */
	if (net_nbuf_family(buf) != AF_INET6) {
		return NET_DROP;
	}

	if (!net_6lo_compress(buf, true, NULL)) {
		NET_DBG("Packet compression failed");
		return NET_DROP;
	}

	net_if_queue_tx(ctxt->iface, buf);

	return NET_OK;
}
コード例 #11
0
ファイル: slip.c プロジェクト: zmole945/zephyr
static u8_t *recv_cb(u8_t *buf, size_t *off)
{
	struct slip_context *slip =
		CONTAINER_OF(buf, struct slip_context, buf);
	size_t i;

	if (!slip->init_done) {
		*off = 0;
		return buf;
	}

	for (i = 0; i < *off; i++) {
		if (slip_input_byte(slip, buf[i])) {
#if SYS_LOG_LEVEL >= SYS_LOG_LEVEL_DEBUG
			struct net_buf *frag = slip->rx->frags;
			int bytes = net_buf_frags_len(frag);
			int count = 0;

			while (bytes && frag) {
				char msg[8 + 1];

				snprintf(msg, sizeof(msg), ">slip %2d", count);

				hexdump(msg, frag->data, frag->len, 0);

				frag = frag->frags;
				count++;
			}

			SYS_LOG_DBG("[%p] received data %d bytes", slip, bytes);
#endif
			process_msg(slip);
			break;
		}
	}

	*off = 0;

	return buf;
}
コード例 #12
0
ファイル: dhcpv4.c プロジェクト: sunkaizhu/zephyr
static enum net_verdict net_dhcpv4_input(struct net_conn *conn,
					 struct net_buf *buf,
					 void *user_data)
{
	struct dhcp_msg *msg;
	struct net_buf *frag;
	struct net_if *iface;
	uint8_t	msg_type;
	uint8_t min;
	uint16_t pos;

	if (!conn) {
		NET_DBG("Invalid connection");
		return NET_DROP;
	}

	if (!buf || !buf->frags) {
		NET_DBG("Invalid buffer, no fragments");
		return NET_DROP;
	}

	iface = net_nbuf_iface(buf);
	if (!iface) {
		return NET_DROP;
	}

	frag = buf->frags;
	min = NET_IPV4UDPH_LEN + sizeof(struct dhcp_msg);

	/*
	 * If the message is not DHCP then continue passing to
	 * related handlers.
	 */
	if (net_buf_frags_len(frag) < min) {
		NET_DBG("Input msg is not related to DHCPv4");
		return NET_CONTINUE;

	}

	msg = (struct dhcp_msg *)(frag->data + NET_IPV4UDPH_LEN);

	NET_DBG("received dhcp msg [op=0x%x htype=0x%x hlen=%u xid=0x%x "
		"secs=%u flags=0x%x ciaddr=%d.%d.%d.%d yiaddr=%d.%d.%d.%d "
		"siaddr=%d.%d.%d.%d giaddr=%d.%d.%d.%d chaddr=%s]",
		msg->op, msg->htype, msg->hlen, ntohl(msg->xid),
		msg->secs, msg->flags,
		msg->ciaddr[0], msg->ciaddr[1], msg->ciaddr[2], msg->ciaddr[3],
		msg->yiaddr[0], msg->yiaddr[1], msg->yiaddr[2], msg->yiaddr[3],
		msg->siaddr[0], msg->siaddr[1], msg->siaddr[2], msg->siaddr[3],
		msg->giaddr[0], msg->giaddr[1], msg->giaddr[2], msg->giaddr[3],
		net_sprint_ll_addr(msg->chaddr, 6));

	if (!(msg->op == DHCPV4_MSG_BOOT_REPLY &&
	      iface->dhcpv4.xid == ntohl(msg->xid) &&
	      !memcmp(msg->chaddr, iface->link_addr.addr,
		      iface->link_addr.len))) {

		NET_DBG("Unexpected op (%d), xid (%x vs %x) or chaddr",
			msg->op, iface->dhcpv4.xid, ntohl(msg->xid));
		goto drop;
	}

	memcpy(iface->dhcpv4.requested_ip.s4_addr, msg->yiaddr,
	       sizeof(msg->yiaddr));

	/* sname, file are not used at the moment, skip it */
	frag = net_nbuf_skip(frag, min, &pos, SIZE_OF_SNAME + SIZE_OF_FILE);
	if (!frag && pos) {
		goto drop;
	}

	if (parse_options(iface, frag, pos, &msg_type) == NET_DROP) {
		NET_DBG("Invalid Options");
		goto drop;
	}

	net_nbuf_unref(buf);

	handle_dhcpv4_reply(iface, msg_type);

	return NET_OK;

drop:
	return NET_DROP;
}