1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

Merge pull request #3183 from authmillenon/ng_ipv6/enh/loopback

ng_ipv6: add loopback support
This commit is contained in:
Martine Lenders 2015-07-14 15:11:02 +02:00
commit c14587f829

View File

@ -285,19 +285,28 @@ static int _fill_ipv6_hdr(kernel_pid_t iface, ng_pktsnip_t *ipv6,
DEBUG("ipv6: set next header to %" PRIu8 "\n", hdr->nh); DEBUG("ipv6: set next header to %" PRIu8 "\n", hdr->nh);
if (hdr->hl == 0) { if (hdr->hl == 0) {
hdr->hl = ng_ipv6_netif_get(iface)->cur_hl; if (iface == KERNEL_PID_UNDEF) {
hdr->hl = NG_IPV6_NETIF_DEFAULT_HL;
}
else {
hdr->hl = ng_ipv6_netif_get(iface)->cur_hl;
}
} }
if (ng_ipv6_addr_is_unspecified(&hdr->src)) { if (ng_ipv6_addr_is_unspecified(&hdr->src)) {
ng_ipv6_addr_t *src = ng_ipv6_netif_find_best_src_addr(iface, &hdr->dst); if (ng_ipv6_addr_is_loopback(&hdr->dst)) {
ng_ipv6_addr_set_loopback(&hdr->src);
if (src != NULL) {
DEBUG("ipv6: set packet source to %s\n",
ng_ipv6_addr_to_str(addr_str, src, sizeof(addr_str)));
memcpy(&hdr->src, src, sizeof(ng_ipv6_addr_t));
} }
else {
ng_ipv6_addr_t *src = ng_ipv6_netif_find_best_src_addr(iface, &hdr->dst);
/* Otherwise leave unspecified */ if (src != NULL) {
DEBUG("ipv6: set packet source to %s\n",
ng_ipv6_addr_to_str(addr_str, src, sizeof(addr_str)));
memcpy(&hdr->src, src, sizeof(ng_ipv6_addr_t));
}
/* Otherwise leave unspecified */
}
} }
DEBUG("ipv6: calculate checksum for upper header.\n"); DEBUG("ipv6: calculate checksum for upper header.\n");
@ -456,6 +465,7 @@ static void _send(ng_pktsnip_t *pkt, bool prep_hdr)
{ {
kernel_pid_t iface = KERNEL_PID_UNDEF; kernel_pid_t iface = KERNEL_PID_UNDEF;
ng_pktsnip_t *ipv6, *payload; ng_pktsnip_t *ipv6, *payload;
ng_ipv6_addr_t *tmp;
ng_ipv6_hdr_t *hdr; ng_ipv6_hdr_t *hdr;
/* seize payload as temporary variable */ /* seize payload as temporary variable */
payload = ng_pktbuf_start_write(pkt); payload = ng_pktbuf_start_write(pkt);
@ -480,11 +490,50 @@ static void _send(ng_pktsnip_t *pkt, bool prep_hdr)
} }
hdr = ipv6->data; hdr = ipv6->data;
payload = ipv6->next; /* TODO: parse extension headers */ payload = ipv6->next;
if (ng_ipv6_addr_is_multicast(&hdr->dst)) { if (ng_ipv6_addr_is_multicast(&hdr->dst)) {
_send_multicast(iface, pkt, ipv6, payload, prep_hdr); _send_multicast(iface, pkt, ipv6, payload, prep_hdr);
} }
else if ((ng_ipv6_addr_is_loopback(&hdr->dst)) || /* dst is loopback address */
((iface == KERNEL_PID_UNDEF) && /* or dst registered to any local interface */
((iface = ng_ipv6_netif_find_by_addr(&tmp, &hdr->dst)) != KERNEL_PID_UNDEF)) ||
((iface != KERNEL_PID_UNDEF) && /* or dst registered to given interface */
(ng_ipv6_netif_find_addr(iface, &hdr->dst) != NULL))) {
uint8_t *rcv_data;
ng_pktsnip_t *ptr = ipv6, *rcv_pkt;
if (prep_hdr) {
if (_fill_ipv6_hdr(iface, ipv6, payload) < 0) {
/* error on filling up header */
ng_pktbuf_release(pkt);
return;
}
}
rcv_pkt = ng_pktbuf_add(NULL, NULL, ng_pkt_len(ipv6), NG_NETTYPE_IPV6);
if (rcv_pkt == NULL) {
DEBUG("ipv6: error on generating loopback packet\n");
ng_pktbuf_release(pkt);
return;
}
rcv_data = rcv_pkt->data;
/* "reverse" packet (by making it one snip as if received from NIC) */
while (ptr != NULL) {
memcpy(rcv_data, ptr->data, ptr->size);
rcv_data += ptr->size;
ptr = ptr->next;
}
ng_pktbuf_release(pkt);
DEBUG("ipv6: packet is addressed to myself => loopback\n");
ng_netapi_receive(ng_ipv6_pid, rcv_pkt);
}
else { else {
uint8_t l2addr_len = NG_IPV6_NC_L2_ADDR_MAX; uint8_t l2addr_len = NG_IPV6_NC_L2_ADDR_MAX;
uint8_t l2addr[l2addr_len]; uint8_t l2addr[l2addr_len];
@ -513,7 +562,10 @@ static void _send(ng_pktsnip_t *pkt, bool prep_hdr)
/* functions for receiving */ /* functions for receiving */
static inline bool _pkt_not_for_me(kernel_pid_t *iface, ng_ipv6_hdr_t *hdr) static inline bool _pkt_not_for_me(kernel_pid_t *iface, ng_ipv6_hdr_t *hdr)
{ {
if (*iface == KERNEL_PID_UNDEF) { if (ng_ipv6_addr_is_loopback(&hdr->dst)) {
return false;
}
else if (*iface == KERNEL_PID_UNDEF) {
*iface = ng_ipv6_netif_find_by_addr(NULL, &hdr->dst); *iface = ng_ipv6_netif_find_by_addr(NULL, &hdr->dst);
return (*iface == KERNEL_PID_UNDEF); return (*iface == KERNEL_PID_UNDEF);
} }