void gnrc_sixlowpan_frag_handle_pkt(gnrc_pktsnip_t *pkt) { gnrc_netif_hdr_t *hdr = pkt->next->data; sixlowpan_frag_t *frag = pkt->data; uint16_t offset = 0; size_t frag_size; switch (frag->disp_size.u8[0] & SIXLOWPAN_FRAG_DISP_MASK) { case SIXLOWPAN_FRAG_1_DISP: frag_size = (pkt->size - sizeof(sixlowpan_frag_t)); break; case SIXLOWPAN_FRAG_N_DISP: offset = (((sixlowpan_frag_n_t *)frag)->offset * 8); frag_size = (pkt->size - sizeof(sixlowpan_frag_n_t)); break; default: DEBUG("6lo rbuf: Not a fragment header.\n"); gnrc_pktbuf_release(pkt); return; } rbuf_add(hdr, pkt, frag_size, offset); gnrc_pktbuf_release(pkt); }
void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page) { gnrc_netif_hdr_t *hdr = pkt->next->data; sixlowpan_frag_t *frag = pkt->data; uint16_t offset = 0; (void)ctx; switch (frag->disp_size.u8[0] & SIXLOWPAN_FRAG_DISP_MASK) { case SIXLOWPAN_FRAG_1_DISP: break; case SIXLOWPAN_FRAG_N_DISP: offset = (((sixlowpan_frag_n_t *)frag)->offset * 8); break; default: DEBUG("6lo rbuf: Not a fragment header.\n"); gnrc_pktbuf_release(pkt); return; } rbuf_add(hdr, pkt, offset, page); }
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, size_t frag_size, size_t offset) { rbuf_t *entry; /* cppcheck-suppress variableScope * (reason: cppcheck is clearly wrong here) */ unsigned int data_offset = 0; size_t original_size = frag_size; sixlowpan_frag_t *frag = pkt->data; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t); _rbuf_gc(); entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len, byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK, byteorder_ntohs(frag->tag)); if (entry == NULL) { DEBUG("6lo rbuf: reassembly buffer full.\n"); return; } ptr = entry->ints; /* dispatches in the first fragment are ignored */ if (offset == 0) { if (data[0] == SIXLOWPAN_UNCOMP) { data++; /* skip 6LoWPAN dispatch */ frag_size--; } #ifdef MODULE_GNRC_SIXLOWPAN_IPHC else if (sixlowpan_iphc_is(data)) { size_t iphc_len, nh_len = 0; iphc_len = gnrc_sixlowpan_iphc_decode(&entry->pkt, pkt, entry->pkt->size, sizeof(sixlowpan_frag_t), &nh_len); if (iphc_len == 0) { DEBUG("6lo rfrag: could not decode IPHC dispatch\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } data += iphc_len; /* take remaining data as data */ frag_size -= iphc_len; /* and reduce frag size by IPHC dispatch length */ /* but add IPv6 header + next header lengths */ frag_size += sizeof(ipv6_hdr_t) + nh_len; /* start copying after IPv6 header and next headers */ data_offset += sizeof(ipv6_hdr_t) + nh_len; } #endif } else { data++; /* FRAGN header is one byte longer (offset) */ } if ((offset + frag_size) > entry->pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } /* If the fragment overlaps another fragment and differs in either the size * or the offset of the overlapped fragment, discards the datagram * https://tools.ietf.org/html/rfc4944#section-5.3 */ while (ptr != NULL) { if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); /* "A fresh reassembly may be commenced with the most recently * received link fragment" * https://tools.ietf.org/html/rfc4944#section-5.3 */ rbuf_add(netif_hdr, pkt, original_size, offset); return; } ptr = ptr->next; } if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); entry->cur_size += (uint16_t)frag_size; memcpy(((uint8_t *)entry->pkt->data) + offset + data_offset, data, frag_size - data_offset); } if (entry->cur_size == entry->pkt->size) { gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(entry->src, entry->src_len, entry->dst, entry->dst_len); if (netif == NULL) { DEBUG("6lo rbuf: error allocating netif header\n"); gnrc_pktbuf_release(entry->pkt); _rbuf_rem(entry); return; } /* copy the transmit information of the latest fragment into the newly * created header to have some link_layer information. The link_layer * info of the previous fragments is discarded. */ gnrc_netif_hdr_t *new_netif_hdr = netif->data; new_netif_hdr->if_pid = netif_hdr->if_pid; new_netif_hdr->flags = netif_hdr->flags; new_netif_hdr->lqi = netif_hdr->lqi; new_netif_hdr->rssi = netif_hdr->rssi; LL_APPEND(entry->pkt, netif); if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, entry->pkt)) { DEBUG("6lo rbuf: No receivers for this packet found\n"); gnrc_pktbuf_release(entry->pkt); } _rbuf_rem(entry); } }
static void buffered_filters(args_t *args, bcf1_t *line) { /** * The logic of SnpGap=3. The SNPs at positions 1 and 7 are filtered, * positions 0 and 8 are not: * 0123456789 * ref .G.GT..G.. * del .A.G-..A.. * Here the positions 1 and 6 are filtered, 0 and 7 are not: * 0123-456789 * ref .G.G-..G.. * ins .A.GT..A.. * * The logic of IndelGap=2. The second indel is filtered: * 012345678901 * ref .GT.GT..GT.. * del .G-.G-..G-.. * And similarly here, the second is filtered: * 01 23 456 78 * ref .A-.A-..A-.. * ins .AT.AT..AT.. */ // To avoid additional data structure, we abuse bcf1_t's var and var_type records. const int SnpGap_set = VCF_OTHER<<1; const int IndelGap_set = VCF_OTHER<<2; const int IndelGap_flush = VCF_OTHER<<3; int var_type = 0, i; if ( line ) { // Still on the same chromosome? int ilast = rbuf_last(&args->rbuf); if ( ilast>=0 && line->rid != args->rbuf_lines[ilast]->rid ) flush_buffer(args, args->rbuf.n); // new chromosome, flush everything // Insert the new record in the buffer. The line would be overwritten in // the next bcf_sr_next_line call, therefore we need to swap it with an // unused one ilast = rbuf_add(&args->rbuf); if ( !args->rbuf_lines[ilast] ) args->rbuf_lines[ilast] = bcf_init1(); SWAP(bcf1_t*, args->files->readers[0].buffer[0], args->rbuf_lines[ilast]); var_type = bcf_get_variant_types(line); // Find out the size of an indel. The indel boundaries are based on REF // (POS+1,POS+rlen-1). This is not entirely correct: mpileup likes to // output REF=CAGAGAGAGA, ALT=CAGAGAGAGAGA where REF=C,ALT=CGA could be // used. This filter is therefore more strict and may remove some valid // SNPs. int len = 1; if ( var_type & VCF_INDEL ) { for (i=1; i<line->n_allele; i++) if ( len < 1-line->d.var[i].n ) len = 1-line->d.var[i].n; } // Set the REF allele's length to max deletion length or to 1 if a SNP or an insertion. line->d.var[0].n = len; } int k_flush = 0; if ( args->indel_gap ) { // Find indels which are too close to each other int last_to = -1; for (i=-1; rbuf_next(&args->rbuf,&i); ) { bcf1_t *rec = args->rbuf_lines[i]; int rec_from = rec->pos; if ( last_to!=-1 && last_to < rec_from ) break; k_flush++; if ( !(rec->d.var_type & VCF_INDEL) ) continue; rec->d.var_type |= IndelGap_set; last_to = args->indel_gap + rec->pos + rec->d.var[0].n - 1; } if ( i==args->rbuf.f && line && last_to!=-1 ) k_flush = 0; if ( k_flush || !line ) { // Select the best indel from the cluster of k_flush indels int k = 0, max_ac = -1, imax_ac = -1; for (i=-1; rbuf_next(&args->rbuf,&i) && k<k_flush; ) { k++; bcf1_t *rec = args->rbuf_lines[i]; if ( !(rec->d.var_type & IndelGap_set) ) continue; hts_expand(int, rec->n_allele, args->ntmpi, args->tmpi); int ret = bcf_calc_ac(args->hdr, rec, args->tmpi, BCF_UN_ALL); if ( imax_ac==-1 || (ret && max_ac < args->tmpi[1]) ) { max_ac = args->tmpi[1]; imax_ac = i; } } // Filter all but the best indel (with max AF or first if AF not available) k = 0; for (i=-1; rbuf_next(&args->rbuf,&i) && k<k_flush; ) { k++; bcf1_t *rec = args->rbuf_lines[i]; if ( !(rec->d.var_type & IndelGap_set) ) continue; rec->d.var_type |= IndelGap_flush; if ( i!=imax_ac ) bcf_add_filter(args->hdr, args->rbuf_lines[i], args->IndelGap_id); } }
void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt, size_t offset, unsigned page) { rbuf_t *entry; sixlowpan_frag_t *frag = pkt->data; rbuf_int_t *ptr; uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t); size_t frag_size; rbuf_gc(); entry = _rbuf_get(gnrc_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len, gnrc_netif_hdr_get_dst_addr(netif_hdr), netif_hdr->dst_l2addr_len, byteorder_ntohs(frag->disp_size) & SIXLOWPAN_FRAG_SIZE_MASK, byteorder_ntohs(frag->tag), page); if (entry == NULL) { DEBUG("6lo rbuf: reassembly buffer full.\n"); return; } ptr = entry->ints; /* dispatches in the first fragment are ignored */ if (offset == 0) { frag_size = pkt->size - sizeof(sixlowpan_frag_t); if (data[0] == SIXLOWPAN_UNCOMP) { frag_size--; } } else { frag_size = pkt->size - sizeof(sixlowpan_frag_n_t); data++; /* FRAGN header is one byte longer (offset) */ } if ((offset + frag_size) > entry->super.pkt->size) { DEBUG("6lo rfrag: fragment too big for resulting datagram, discarding datagram\n"); gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); return; } /* If the fragment overlaps another fragment and differs in either the size * or the offset of the overlapped fragment, discards the datagram * https://tools.ietf.org/html/rfc4944#section-5.3 */ while (ptr != NULL) { if (_rbuf_int_overlap_partially(ptr, offset, offset + frag_size - 1)) { DEBUG("6lo rfrag: overlapping intervals, discarding datagram\n"); gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); /* "A fresh reassembly may be commenced with the most recently * received link fragment" * https://tools.ietf.org/html/rfc4944#section-5.3 */ rbuf_add(netif_hdr, pkt, offset, page); return; } ptr = ptr->next; } if (_rbuf_update_ints(entry, offset, frag_size)) { DEBUG("6lo rbuf: add fragment data\n"); entry->super.current_size += (uint16_t)frag_size; if (offset == 0) { #ifdef MODULE_GNRC_SIXLOWPAN_IPHC if (sixlowpan_iphc_is(data)) { gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt, sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN); if (frag_hdr == NULL) { gnrc_pktbuf_release(entry->super.pkt); rbuf_rm(entry); return; } gnrc_sixlowpan_iphc_recv(pkt, &entry->super, 0); return; } else #endif if (data[0] == SIXLOWPAN_UNCOMP) { data++; } } memcpy(((uint8_t *)entry->super.pkt->data) + offset, data, frag_size); } gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(&entry->super, netif_hdr); gnrc_pktbuf_release(pkt); }