static int icmp_dispatch(struct sk_buff *skb, const struct pal_dip *dip) { struct ip_hdr *iph = (struct ip_hdr *)skb_ip_header(skb); struct icmp_hdr *icmph = skb_icmp_header(skb); unsigned icmp_len = pal_ntohs(iph->tot_len) - (iph->ihl * 4); pal_cur_thread_conf()->stats.ip.icmp.rx_pkts++; pal_cur_thread_conf()->stats.ip.icmp.rx_bytes += skb_l2_len(skb); /* icmp content must be more then 8 bytes */ if (icmp_len >= 8 && icmp_len <= skb_len(skb)) { if (icmp_check_sum_correct((uint16_t *)icmph, icmp_len)) { return dispatch_pkt(skb, dip); } else { pal_cur_thread_conf()->stats.ip.icmp.csum_err++; PAL_DEBUG("Bad icmp checksum\n"); } } else { pal_cur_thread_conf()->stats.ip.icmp.trunc_pkts++; PAL_DEBUG("icmp len < 8, invalid\n"); } return -1; }
static int icmp_handler(struct sk_buff *skb) { struct ip_hdr *iph = (struct ip_hdr *)skb_ip_header(skb); struct icmp_hdr *icmph = skb_icmp_header(skb); unsigned icmp_len = pal_htons(iph->tot_len) - (iph->ihl * 4); uint8_t *l2_dest_mac_p = skb_eth_header(skb)->dst; uint32_t tmp_addr; pal_cur_thread_conf()->stats.ip.icmp.rx_pkts++; pal_cur_thread_conf()->stats.ip.icmp.rx_bytes += skb_l2_len(skb); PAL_DEBUG("in icmp handler\n"); /* icmp content must be more then 8 bytes */ if (icmp_len >= 8 && icmp_len <= skb_len(skb)) { /* we only handle icmp echo request */ if (icmph->type == ICMP_ECHO) { if (icmp_check_sum_correct((uint16_t *)icmph, icmp_len)) { icmph->type = ICMP_ECHOREPLY; /* update icmp check sum*/ icmph->checksum = icmph->checksum + pal_htons_constant(0x0800); /* Exchange ip addresses */ tmp_addr = iph->saddr; iph->saddr = iph->daddr; iph->daddr = tmp_addr; /**update ip ttl*/ iph->ttl = 64; skb_ip_csum_offload(skb, iph->ihl * 4); swap_mac(l2_dest_mac_p); skb_push(skb, (unsigned long)skb_l4_header(skb) - (unsigned long)skb_l2_header(skb)); pal_cur_thread_conf()->stats.ip.icmp.reply_pkts++; if (pal_send_raw_pkt(skb, skb->recv_if) == 0) { PAL_DEBUG("sent icmp reply\n"); return 0; } pal_cur_thread_conf()->stats.ip.icmp.reply_failure++; PAL_DEBUG("send icmp reply failed\n"); } else { pal_cur_thread_conf()->stats.ip.icmp.csum_err++; PAL_DEBUG("Bad icmp checksum\n"); } } else { pal_cur_thread_conf()->stats.ip.icmp.not_echo_pkts++; pal_cur_thread_conf()->stats.ip.icmp.not_echo_bytes += skb_l2_len(skb); PAL_DEBUG("icmp not echo request!\n"); } } else { pal_cur_thread_conf()->stats.ip.icmp.trunc_pkts++; PAL_DEBUG("icmp len < 8, invalid\n"); } return -1; }
int icmp_v4_proxy(struct rte_mbuf *mbuf,struct iphdr *iph) { u32 lcore; s32 icmp_len; s32 ret ; u16 tot_len ; struct ether_hdr *ethdr = rte_pktmbuf_mtod(mbuf,struct ether_hdr *); struct icmphdr *icmph =(struct icmphdr*)((u8*)iph) + ((iph->ihl)<<2); tot_len = iph->tot_len; icmp_len = (s32)(ntohs(tot_len) - (iph->ihl*4)); mbuf->pkt.vlan_macip.f.l2_len = sizeof(*ethdr); mbuf->pkt.vlan_macip.f.l3_len = iph->ihl << 2; if( (icmp_len >= 8) && icmp_check_sum_correct((u16*)icmph, icmp_len) ) { if(icmph->type == ICMP_ECHO) { //US_DEBUG_LINE(); lcore = US_GET_LCORE(); iph->daddr = glb_dest_ip; iph->saddr = us_nic_ports[0].if_ipv4_bip[lcore]; iph->check = 0; iph->ttl--; swap_mac(ethdr); icmph->checksum = 0; icmph->checksum = icmp_check_sum((u8*)icmph,icmp_len); set_ipv4_csum_offload(mbuf); //recv_pkt_dump(&mbuf, 1); goto send_out; } else if(icmph->type == ICMP_ECHOREPLY) { //US_DEBUG_LINE(); iph->daddr = glb_client_ip; iph->saddr = us_nic_ports[0].if_ipv4_vip[0]; iph->check = 0; iph->ttl--; swap_mac(ethdr); icmph->checksum = 0; icmph->checksum = icmp_check_sum((u8*)icmph,icmp_len); set_ipv4_csum_offload(mbuf); //recv_pkt_dump(&mbuf, 1); } else { goto failed_out; } } else { goto failed_out; } send_out: ret = rte_eth_tx_burst(us_nic_ports[0].port_id, 0,&mbuf, 1); if (ret < 1) { goto failed_out; } return US_RET_OK; failed_out: rte_pktmbuf_free(mbuf); return US_EINVAL; }