📄 ipp.nc
字号:
return FALSE;
}
uint8_t cmp_ipv6_addr(const ip6_addr_t *addr1, const ip6_addr_t *addr2)
{
return memcmp(addr1, addr2, sizeof(ip6_addr_t));
}
uint8_t ipv6_addr_is_for_me(const ip6_addr_t *addr)
{
//TODO: loopback addr (::1)
//TODO: interface-local addr FF01::1
if (cmp_ipv6_addr(addr, &global_addr) == 0 ||
cmp_ipv6_addr(addr, &linklocal_addr) == 0 ||
ipv6_addr_is_linklocal_allnodes(addr) ||
(ipv6_addr_is_solicited_node_multicast_prefix(addr)
&& (((addr->addr[13] == global_addr.addr[13])
&& (addr->addr[14] == global_addr.addr[14])
&& (addr->addr[15] == global_addr.addr[15])
) ||
((addr->addr[13] == linklocal_addr.addr[13])
&& (addr->addr[14] == linklocal_addr.addr[14])
&& (addr->addr[15] == linklocal_addr.addr[15])
)
)
)
)
return 1;
else
return 0;
}
/* determine the right src_addr given a dst_addr */
ip6_addr_t * determine_src_ipv6_addr(const ip6_addr_t *dst_addr)
{
if (ipv6_addr_is_linklocal(dst_addr)) {
return &linklocal_addr;
} else {
return &global_addr;
}
}
uint8_t cmp_hw_addr(const hw_addr_t *addr1, const hw_addr_t *addr2)
{
// for short addresses compare only the first two bytes
if (addr1->type == HW_ADDR_SHORT && addr2->type == HW_ADDR_SHORT) {
return memcmp(addr1->addr_short, addr2->addr_short, 2);
} else {
return memcmp(addr1, addr2, sizeof(hw_addr_t));
}
}
uint8_t hw_addr_is_broadcat(const hw_addr_t *hw_addr)
{
if (hw_addr->type == HW_ADDR_SHORT
&& hw_addr->addr_short[0] == 0xFF
&& hw_addr->addr_short[1] == 0xFF)
return 1;
// TODO: long address
else return 0;
}
uint8_t hw_addr_is_for_me(const hw_addr_t *addr)
{
am_addr_t am_addr = call AMPacket.address();
if (hw_addr_is_broadcat(addr) ||
(addr->addr_short[0] == (uint8_t) am_addr
&& addr->addr_short[1] == (uint8_t) (am_addr >> 8))
)
return 1;
else
return 0;
}
/*---------------------------------------------------------------------------*/
void increment_g_dgram_tag()
{
uint16_t tmp = ntohs(g_dgram_tag);
if (tmp == 0xFFFF)
tmp = 0;
else
tmp++;
g_dgram_tag = htons(tmp);
}
void lowpan_pkt_clear(lowpan_pkt_t *pkt)
{
memset(pkt, 0, sizeof(*pkt));
pkt->header_begin = pkt->header + sizeof(pkt->header);
}
/*
void frag_buf_clear(frag_buf_t *frag_buf)
{
memset(frag_buf, 0, sizeof(*frag_buf));
frag_buf->buf_begin = frag_buf->buf;
}
*/
frag_buf_t * find_fragment(hw_addr_t *hw_src_addr, hw_addr_t *hw_dst_addr,
uint16_t dgram_size, uint16_t dgram_tag)
{
int i;
for (i = 0; i< FRAG_BUFS; i++) {
//printf("find_frag\n");
if (frag_bufs[i].frag_timeout != FRAG_FREE) {
//printf("find: [%d] %d\n", i, frag_bufs[i].frag_timeout);
/*
printf("find: tag: 0x%04X, size: %d\n",
get_16t(&frag_bufs[i].dgram_tag),
ntohs(get_16t(&frag_bufs[i].dgram_size)));
*/
if ( get_16t(&(frag_bufs[i].dgram_tag)) == dgram_tag
&& get_16t(&(frag_bufs[i].dgram_size)) == dgram_size
&& cmp_hw_addr(&frag_bufs[i].hw_src_addr, hw_src_addr) == 0
&& cmp_hw_addr(&frag_bufs[i].hw_dst_addr, hw_dst_addr) == 0
) {
return &(frag_bufs[i]);
}
} else {
//printf("find: [%d] FREE\n", i);
}
}
return NULL;
}
void free_frag_list(frag_info_t *p)
{
frag_info_t *q;
while (p) {
q = p->next;
call FragInfoPool.put(p);
p = q;
}
}
/*---------------------------------------------------------------------------*/
void ip_init()
{
//int i;
lastport = 1024;
memset(udp_conns, 0, sizeof(udp_conns));
//memset(&global_addr, 0, sizeof(global_addr));
memset(&linklocal_addr, 0, sizeof(linklocal_addr));
memset(frag_bufs, 0, sizeof(frag_bufs));
/*
for(i=0;i<FAG_BUFS,i++) {
frag_buf_clear(frag_bufs[i]);
}
*/
}
uint16_t udp_assign_port()
{
int c;
/* Find an unused local port. */
again:
++lastport;
if (lastport >= 32000) {
lastport = 4096;
}
for (c = 0; c < COUNT_UDP_CONNS; ++c) {
if (udp_conns[c].lport == lastport) {
goto again;
}
}
return lastport;
}
/* ========================= IPv6 - output ================================= */
task void sendTask()
{
lowpan_pkt_t *pkt = send_queue;
struct lowpan_frag_hdr *frag_hdr;
uint8_t *payload;
uint8_t frame_len;
uint8_t len; /* length of the fragment just being sent
* excluding the 6lowpan optional headers */
uint8_t remaining_len; /* how much more data can we fit
* into this fragment */
uint8_t *tmp_cpy_buf; /* simplifies memcpy */
uint8_t tmp_cpy_len; /* simplifies memcpy */
if (!pkt || g_send_pending) {
return;
}
//len = pkt->header_len + pkt->app_data_len - pkt->dgram_offset*8;
if (pkt->header_len + pkt->app_data_len <= LINK_DATA_MTU) {
/* fragmentation not needed */
frame_len = pkt->header_len + pkt->app_data_len;
/* prepare the AM */
call Packet.clear(&g_msg);
call Packet.setPayloadLength(&g_msg, frame_len);
payload = call Packet.getPayload(&g_msg, frame_len);
// memset(payload, 0 , payload_len);
// should check payload_len here
/* copy header */
if (pkt->header_begin && pkt->header_len)
memcpy(payload, pkt->header_begin, pkt->header_len);
payload += pkt->header_len;
/* copy app_data */
if (pkt->app_data_begin && pkt->app_data_len)
memcpy(payload, pkt->app_data_begin, pkt->app_data_len);
} else {
/* do fragmentation */
if (pkt->dgram_offset == 0) {
/* first fragment */
increment_g_dgram_tag();
set_16t(&pkt->dgram_size,
htons(pkt->header_len + pkt->app_data_len));
/* align fragment length at an 8-byte multiple */
len = LINK_DATA_MTU - sizeof(struct lowpan_frag_hdr);
len -= len%8;
frame_len = len + sizeof(struct lowpan_frag_hdr);
} else {
/* subsequent fragment */
if (pkt->header_len + pkt->app_data_len - pkt->dgram_offset*8
<= LINK_DATA_MTU - sizeof(struct lowpan_frag_hdr)
- sizeof(uint8_t)) {
/* last fragment -- does not have to be aligned
* at an 8-byte multiple */
len = pkt->header_len + pkt->app_data_len
- pkt->dgram_offset*8;
} else {
/* align fragment length at an 8-byte multiple */
len = LINK_DATA_MTU - sizeof(struct lowpan_frag_hdr)
- sizeof(uint8_t);
len -= len%8;
}
frame_len = len + sizeof(struct lowpan_frag_hdr)
+ sizeof(uint8_t);
}
/* prepare the AM */
call Packet.clear(&g_msg);
call Packet.setPayloadLength(&g_msg,frame_len);
payload = call Packet.getPayload(&g_msg, frame_len);
remaining_len = frame_len;
if (remaining_len != frame_len) {
//TODO: report an error
#ifdef ENABLE_PRINTF_DEBUG
printf("payload length does not match requested length\n");
call PrintfFlush.flush();
#endif /* ENABLE_PRINTF_DEBUG */
return;
}
/* fill in the fragment header */
frag_hdr = (struct lowpan_frag_hdr *) payload;
set_16t(&frag_hdr->dgram_size, pkt->dgram_size);
set_16t(&frag_hdr->dgram_tag, g_dgram_tag);
payload += sizeof(struct lowpan_frag_hdr);
remaining_len -= sizeof(struct lowpan_frag_hdr);
if (pkt->dgram_offset == 0) {
/* first fragment */
frag_hdr->dispatch |= DISPATCH_FIRST_FRAG;
} else {
/* subsequent fragment */
frag_hdr->dispatch |= DISPATCH_SUBSEQ_FRAG;
*payload = pkt->dgram_offset;
payload += sizeof(uint8_t);
}
/* copy header */
if (pkt->header_begin
&& pkt->header_len
&& pkt->header_len > pkt->dgram_offset*8
/* don't copy the header if offset is beyond it*/
) {
/* determine what has to be copied */
tmp_cpy_buf = pkt->header_begin + pkt->dgram_offset*8;
tmp_cpy_len = min(pkt->header_len - pkt->dgram_offset*8,
remaining_len);
/* copy it */
memcpy(payload, tmp_cpy_buf, tmp_cpy_len);
payload += tmp_cpy_len;
remaining_len -= tmp_cpy_len;
}
/* copy app_data */
if (remaining_len
&& pkt->app_data_begin
&& pkt->app_data_len
) {
/* determine what has to be copied */
if (pkt->dgram_offset*8 > pkt->header_len) {
tmp_cpy_buf = pkt->app_data_begin
+ pkt->dgram_offset*8 - pkt->header_len;
} else {
/* header has been copied only now, offset not yet updated */
tmp_cpy_buf = pkt->app_data_begin;
}
tmp_cpy_len = min(remaining_len,
pkt->app_data_len
- (pkt->dgram_offset*8 - pkt->header_len));
/* copy it */
memcpy(payload, tmp_cpy_buf, tmp_cpy_len);
payload += tmp_cpy_len;
remaining_len -= tmp_cpy_len;
}
/* update the offset - in 8-byte multiples */
pkt->dgram_offset += len/8;
if (len%8) {
/* last fragment with a special length */
pkt->dgram_offset++;
}
}
/* send the AM */
g_send_pending = 1;
call AMSend.send(AM_BROADCAST_ADDR, &g_msg, frame_len);
//call AMSend.send(0x12, &g_msg, frame_len);
}
event void AMSend.sendDone(message_t* msg, error_t error)
{
uint16_t len;
lowpan_pkt_t *pkt = send_queue;
g_send_pending = 0;
if (!send_queue) {
// somethign really went wrong...
return;
}
len = pkt->header_len + pkt->app_data_len;
if (len <= LINK_DATA_MTU || pkt->dgram_offset*8 >= len){
/* packet has been completely sent, we can move on to the next one */
/* UDPClient.sendDone notification */
if (send_queue->notify_num != LOWPAN_PKT_NO_NOTIFY) {
signal UDPClient.sendDone[send_queue->notify_num - 1]
(SUCCESS, send_queue->app_data);
}
/* deallocation of app_data (fragment reassembly buffer) */
if (send_queue->app_data_dealloc == APP_DATA_DEALLOC_TRUE
&& send_queue->app_data) {
call AppDataPool.put((app_data_t*) send_queue->app_data);
send_queue->app_data = NULL;
}
pkt = send_queue->next;
call SendPktPool.put(send_queue);
send_queue = pkt;
}
if (send_queue) {
post sendTask();
}
}
void ipv6_output_uncompressed(lowpan_pkt_t *pkt, const uint8_t next_header)
{
struct ip6_hdr *hdr;
lowpan_pkt_t *p;
pkt->header_begin -= sizeof(struct ip6_hdr);
pkt->header_len += sizeof(struct ip6_hdr);
hdr = (struct ip6_hdr *) pkt->header_begin;
/* fill in the IPv6 header */
hdr->vtc = IPV6_VERSION; /* IPv6 version */
/* payload length */
set_16t(&hdr->plen, htons(pkt->header_len + pkt->app_data_len
- sizeof(struct ip6_hdr)));
hdr->nxt_hdr = next_header;
hdr->hlim = IP_HOP_LIMIT; /* hop limit */
memcpy(&hdr->src_addr, &pkt->ip_src_addr, sizeof(hdr->src_addr));
memcpy(&hdr->dst_addr, &pkt->ip_dst_addr, sizeof(hdr->dst_addr));
/* set 6lowpan dispatch value */
pkt->header_begin -= sizeof(uint8_t);
pkt->header_len += sizeof(uint8_t);
*(pkt->header_begin) = DISPATCH_UNCOMPRESSED_IPV6;
//TODO: check if neighbor is information available
// if yes
// fill in hw_addr
// append to send_queue
// else
// append to neighbor_queue
// request ND, add an entry into the neighbor table
/* append pkt to send queue */
if(!send_queue) {
send_queue = pkt;
} else {
for(p=send_queue; p->next; p=p->next);
p->next = pkt;
}
/* schedule sendTask */
post sendTask();
}
/* determines length of the inline carried fields for the HC1 encoding
* the return value is the number of bits, bot bytes !!!
*/
int get_hc1_length(uint8_t hc1_enc)
{
int len = 0;
/* Hop Limit always carried inline */
len += 8;
/* source IP address */
if ((hc1_enc & HC1_SRC_PREFIX_MASK) == HC1_SRC_PREFIX_INLINE)
len += 64;
if ((hc1_enc & HC1_SRC_IFACEID_MASK) == HC1_SRC_IFACEID_INLINE)
len += 64;
/* destination IP address */
if ((hc1_enc & HC1_DST_PREFIX_MASK) == HC1_DST_PREFIX_INLINE)
len += 64;
if ((hc1_enc & HC1_DST_IFACEID_MASK) == HC1_DST_IFACEID_INLINE)
len += 64;
/* Traffic Class and Flow Label */
if ((hc1_enc & HC1_TCFL_MASK) == HC1_TCFL_INLINE)
len += 24;
/* Next Header */
if ((hc1_enc & HC1_NEXTHDR_MASK) == HC1_NEXTHDR_INLINE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -