📄 serial_tun.c
字号:
fragment_t progress;
uint8_t serial[LOWPAN_LINK_MTU + 1];
IEEE154_header_t *radioPacket = (IEEE154_header_t *)(serial + 1);
#define PKTLEN(X) ((X)->length + 2)
uint8_t *lowpan = (uint8_t *)(radioPacket + 1);
#define LOWPAN_PAYLOAD_LENGTH (LOWPAN_LINK_MTU - MAC_HEADER_SIZE \
- MAC_FOOTER_SIZE)
progress.offset = 0;
// and IEEE 802.15.4 header
// write_radio_header(serial, dest, frag_len);
while ((frag_len = getNextFrag(msg, &progress, lowpan,
LOWPAN_PAYLOAD_LENGTH)) > 0) {
//debug("frag len: 0x%x offset: 0x%x plen: 0x%x\n", frag_len, progress.offset * 8, ntohs(ip_header->plen));
write_radio_header(serial, dest, frag_len);
// if this is sent too fast, the base station can't keep up. The effect of this is
// we send incomplete fragment. 25ms seems to work pretty well.
// 6-9-08 : SDH : this is a bad fix that does not address the
// problem.
// at the very least, the serial ack's seem to be
// working, so we should be retrying if the ack is failing
// because the hardware cannot keep up.
// 9-17-09 : SDH : it seems we've tracked this down to packets
// arriving too fast to enqueue, especially at higher baud rates
// (115200). reenabled to prevent retries, which are very slow.
#ifdef __TARGET_mips__
usleep(50000);
#else
usleep(25000);
#endif
log_dump_serial_packet(serial, PKTLEN(radioPacket));
result = write_pan_packet(serial, PKTLEN(radioPacket));
if (result != 0)
result = write_pan_packet(serial, PKTLEN(radioPacket));
debug("send_fragments: result: 0x%x len: 0x%x\n", result, frag_len);
log_dump_serial_packet(serial, PKTLEN(radioPacket));
stats.tx_frags++;
stats.tx_bytes += PKTLEN(radioPacket);
}
keepalive_needed = 0;
stats.tx_pkts++;
}
void icmp_unreachable(struct split_ip_msg *msg) {
}
/*
* this function takes a complete IP packet, and sends it out to a
* destination in the PAN. It will insert source routing headers and
* recompute L4 checksums as necessary.
*
*/
uint8_t ip_to_pan(struct split_ip_msg *msg) {
int nxt_hdr = msg->hdr.nxt_hdr;
uint16_t dest;
debug("ip_to_pan\n");
print_ip_packet(msg);
// if this packet has a source route (rinstall header, or prexisting
// source header, we don't want to mess with it
switch (routing_is_onehop(msg)) {
case ROUTE_MHOP:
debug("Multihop packet\n");
if (routing_insert_route(msg)) goto fail;
break;
case ROUTE_WORMHOLE:
debug("Wormhole packet\n");
// fall through
case ROUTE_NO_ROUTE:
tun_write(tun_fd, msg);
// info("destination unreachable: 0x%x: dropping\n", ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
return 0;
}
dest = routing_get_nexthop(msg);
debug("next hop: 0x%x\n", dest);
flow_insert_label(msg);
print_ip_packet(msg);
fifo_report(msg, dest, nxt_hdr);
send_fragments(msg, dest);
return 0;
fail:
error("ip_to_pan: no route to host\n");
return 1;
}
void upd_source_route(struct ip6_route *sh, ieee154_saddr_t addr) {
if (sh->segs_remain > 0) {
sh->hops[ROUTE_NENTRIES(sh) - sh->segs_remain] = leton16(addr);
sh->segs_remain--;
}
}
int process_dest_tlv(struct ip6_hdr *iph, struct ip6_ext *hdr, int len) {
struct tlv_hdr *tlv = (struct tlv_hdr *)(hdr + 1);
node_id_t reporter = ntohs(iph->ip6_src.s6_addr16[7]);
if (len != hdr-> len) return 1;
len -= sizeof(struct ip6_ext);
while (tlv != NULL && len > 0) {
if (tlv->len == 0) return 1;
switch(tlv->type) {
case TLV_TYPE_TOPOLOGY:
routing_add_report(reporter, tlv);
break;
}
len -= tlv->len;
tlv = (struct tlv_hdr *)(((uint8_t *)tlv) + tlv->len);
}
return 0;
}
int process_hop_tlv(struct split_ip_msg *msg, struct ip6_ext *hdr, int len) {
struct tlv_hdr *tlv = (struct tlv_hdr *)(hdr + 1);
uint16_t *fl;
if (len != hdr-> len) return 1;
len -= sizeof(struct ip6_ext);
while (tlv != NULL && len > 0) {
if (tlv->len == 0) return 1;
switch(tlv->type) {
case TLV_TYPE_FLOW:
fl = (uint16_t *)(tlv + 1);
msg->flow_id = *fl;
debug("process_hop_tlv: flow 0x%x\n", msg->flow_id);
break;
}
len -= tlv->len;
tlv = (struct tlv_hdr *)(((uint8_t *)tlv) + tlv->len);
}
return 0;
}
int process_extensions(struct split_ip_msg *msg) {
struct generic_header *prev = NULL, *cur = msg->headers;
struct ip6_route *route;
uint8_t nxt_hdr = msg->hdr.nxt_hdr;
int lendelta = 0;
while (cur != NULL && EXTENSION_HEADER(nxt_hdr)) {
debug("dropping header type 0x%x, len %i\n", nxt_hdr, cur->len);
msg->headers = cur->next;
msg->hdr.nxt_hdr = cur->hdr.ext->nxt_hdr;
lendelta += cur->len;
switch (nxt_hdr) {
case IPV6_DEST:
if (process_dest_tlv(&msg->hdr, cur->hdr.ext, cur->len))
return 1;
break;
case IPV6_HOP:
if (process_hop_tlv(msg, cur->hdr.ext, cur->len)) {
warn("dropping packet due to hop tlv\n");
return 1;
}
break;
case IPV6_ROUTING:
route = cur->hdr.sh;
if ((route->type & ~IP6ROUTE_FLAG_MASK) == IP6ROUTE_TYPE_INVAL || route->segs_remain == 0) {
/* if (route->type == IP6ROUTE_TYPE_INVAL) { */
/* if (route->hops[0] == __my_address.s6_addr16[7]) { */
/* warn("dropping packet since it has an invalid source route and I sent it\n"); */
/* return 1; */
/* } */
/* } */
} else {
uint16_t target_hop = ntohs(route->hops[ROUTE_NENTRIES(route) - route->segs_remain]);
// if this is actually a valid source route, maybe update it
// (even though we're going to delete it shortly)
if (target_hop != __my_address.s6_addr16[7]) {
if (ROUTE_NENTRIES(route) >= 2) {
route->hops[0] = htons(msg->prev_hop);
route->hops[1] = htons(target_hop);
}
route->type = (route->type & IP6ROUTE_FLAG_MASK) | IP6ROUTE_TYPE_INVAL;
} else {
route->hops[ROUTE_NENTRIES(route) - route->segs_remain] = htons(msg->prev_hop);
route->segs_remain--;
}
}
if ((route->type & ~IP6ROUTE_FLAG_MASK) == IP6ROUTE_TYPE_INVAL && ROUTE_NENTRIES(route) >= 2) {
node_id_t n1 = ntohs(route->hops[0]);
node_id_t n2 = ntohs(route->hops[1]);
warn ("broken link was %i -> %i\n", n1, n2);
nw_remove_link(n1, n2);
if (route->type & IP6ROUTE_FLAG_CONTROLLER) {
warn("dropping packet since it has an invalid source route and I sent it\n");
return 1;
} else {
warn("received broken source route based on installed route-- uninstalling\n");
/* uninstall_route(ntohs(msg->hdr.ip6_src.s6_addr16[7]), */
/* ntohs(msg->hdr.ip6_dst.s6_addr16[7])); */
}
}
}
nxt_hdr = cur->hdr.ext->nxt_hdr;
prev = cur;
cur = cur->next;
free(prev);
}
msg->hdr.plen = htons(ntohs(msg->hdr.plen) - lendelta);
return 0;
}
#if 0
int remove_sourceroute(struct split_ip_msg *msg) {
struct source_header *s;
struct rinstall_header *rih;
struct generic_header *g_hdr;
uint8_t removeSource = 1;
if (msg->hdr.nxt_hdr == NXTHDR_SOURCE) {
sh = msg->headers->hdr.sh;
upd_source_route(sh, msg->metadata.sender);
// Our thinking here is that if something is source_routed
// from inside the network and it is not destined to us
// then its either a rinstall being forwarded, or a path
// that's been set up, so we shouldn't strip it away
if (cmpPfx(msg->hdr.ip6_dst.s6_addr, __my_address.s6_addr) &&
msg->hdr.ip6_dst.s6_addr16[7] != __my_address.s6_addr16[7]) {
/* ((msg->hdr.ip6_dst.s6_addr[14] != __my_address[14] || */
/* msg->hdr.ip6_dst.s6_addr[15] != __my_address[15]))) { */
info("Packet with source header not destined for me\n");
if ((sh->dispatch & IP_EXT_SOURCE_INVAL) != IP_EXT_SOURCE_INVAL) {
debug("Removing invalid source header\n");
removeSource = 0;
}
if ((sh->dispatch & IP_EXT_SOURCE_CONTROLLER) == IP_EXT_SOURCE_CONTROLLER) {
debug("WE sent this packet! dropping...\n");
return 1;
}
// If this is an rinstall header moving through, we need to
// updated the current position of the path, similar to
// what we do for source headers.
if (sh->nxt_hdr == NXTHDR_INSTALL) {
rih = msg->headers->next->hdr.rih;
rih->current++;
info("Incrementing current of rih to 0x%x\n", rih->current);
}
}
if (removeSource) {
msg->hdr.nxt_hdr = sh->nxt_hdr;
msg->hdr.plen = htons(ntohs(msg->hdr.plen) - sh->len);
g_hdr = msg->headers;
msg->headers = msg->headers->next;
free(g_hdr);
}
}
return 0;
}
#endif
void handle_serial_packet(struct split_ip_msg *msg) {
path_t* tPath;
path_t* i;
#ifdef CENTRALIZED_ROUTING
uint8_t flags = 0x00;
#endif
if (ntohs(msg->hdr.plen) > INET_MTU - sizeof(struct ip6_hdr)) {
warn("handle_ip_packet: too long: 0x%x\n", ntohs(msg->hdr.plen));
return;
}
// print_ip_packet(msg);
print_ip_packet(msg);
if (process_extensions(msg))
return;
if (cmpPfx(msg->hdr.ip6_dst.s6_addr, __my_address.s6_addr) &&
msg->hdr.ip6_dst.s6_addr16[7] != __my_address.s6_addr16[7]) {
debug("Received packet destined to 0x%x\n", msg->hdr.ip6_dst.s6_addr[15]);
stats.fw_pkts++;
// If this packet is not source routed, check to see if we're on the best path before
// issuing a route install
tPath = nw_get_route(ntohs(msg->hdr.ip6_src.s6_addr16[7]), ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
for (i = tPath; i != NULL; i = i->next) {
if (i->node == ntohs(__my_address.s6_addr16[7])) {
debug("Not installing route for packet from 0x%x to 0x%x (on best path)\n",
ntohs(msg->hdr.ip6_src.s6_addr16[7]), ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
nw_free_path(tPath);
ip_to_pan(msg);
return;
}
}
nw_free_path(tPath);
// }
// We send the route installation packet before forwarding the actual
// packet, with the thinking being that the route can be set up, in
// case acks are issued by the destination on the packet
//
// We have to first select the flags that we want:
// At this point, if it's not source routed, then this packet
// shouldn't be coming through us so we install a route
// if (msg->hdr.nxt_hdr != NXTHDR_SOURCE) {
debug("installing route for packet from 0x%x to 0x%x\n",
ntohs(msg->hdr.ip6_src.s6_addr16[7]), ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
#ifdef CENTRALIZED_ROUTING
#ifndef FULL_PATH_INSTALL
flags = HYDRO_METHOD_SOURCE | HYDRO_INSTALL_REVERSE;
#else
flags = HYDRO_METHOD_HOP | HYDRO_INSTALL_REVERSE;
#endif
// install_route(msg, flags);
#endif
// } else {
// info("Packet had a source header so no route install\n");
// }
ip_to_pan(msg);
// do routing
} else {
// give it to linux
// need to remove route info here.
stats.rx_pkts++;
tun_write(tun_fd, msg);
debug("tun_write: wrote 0x%x bytes\n", sizeof(struct ip6_hdr) + ntohs(msg->hdr.plen));
}
}
void add_header_list(struct split_ip_msg *msg) {
uint8_t nxt_hdr;
struct generic_header *g_hdr, **g_list;
struct ip6_ext *ext = (struct ip6_ext *)msg->next;
uint16_t hdr_len = 0;
// debug("add_header_list for message destined to 0x%x\n", ntohs(msg->hdr.ip6_dst.s6_addr16[7]));
nxt_hdr = msg->hdr.nxt_hdr;
msg->headers = NULL;
g_list = &(msg->headers);
while (EXTENSION_HEADER(nxt_hdr)) {
g_hdr = (struct generic_header *)malloc(sizeof(struct generic_header));
g_hdr->payload_malloced = 0;
g_hdr->hdr.ext = ext;
g_hdr->next = NULL;
*g_list = g_hdr;
g_list = &g_hdr->next;
g_hdr->len = ext->len;
nxt_hdr = ext->nxt_hdr;
ext = (struct ip6_ext *)(((uint8_t *)ext) + ext->len);
hdr_len += g_hdr->len;
}
if (COMPRESSIBLE_TRANSPORT(nxt_hdr)) {
int transport_len;
switch (nxt_hdr) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -