static enum ofp_return_code ofp_output_ipv4_to_gre( odp_packet_t pkt, struct ofp_ifnet *dev_gre, uint16_t vrfid, struct ofp_nh_entry **nh_new) { struct ofp_ip *ip; struct ofp_greip *greip; uint32_t flags; uint8_t l2_size = 0; int32_t offset; *nh_new = ofp_get_next_hop(vrfid, dev_gre->ip_remote, &flags); if (*nh_new == NULL) return OFP_PKT_DROP; ip = odp_packet_l3_ptr(pkt, NULL); /* Remove eth header, prepend gre + ip */ if (odp_packet_has_l2(pkt)) l2_size = odp_packet_l3_offset(pkt) - odp_packet_l2_offset(pkt); offset = sizeof(*greip) - l2_size; if (offset >= 0) greip = odp_packet_push_head(pkt, offset); else greip = odp_packet_pull_head(pkt, -offset); odp_packet_has_l2_set(pkt, 0); odp_packet_l3_offset_set(pkt, 0); if (!greip) return OFP_PKT_DROP; greip->gi_flags = 0; greip->gi_ptype = odp_cpu_to_be_16(OFP_GREPROTO_IP); greip->gi_i.ip_hl = 5; greip->gi_i.ip_v = 4; greip->gi_i.ip_tos = ip->ip_tos; greip->gi_i.ip_len = odp_cpu_to_be_16(odp_be_to_cpu_16(ip->ip_len) + sizeof(*greip)); greip->gi_i.ip_id = ip->ip_id; greip->gi_i.ip_off = 0; greip->gi_i.ip_ttl = ip->ip_ttl; greip->gi_i.ip_p = OFP_IPPROTO_GRE; greip->gi_i.ip_sum = 0; greip->gi_i.ip_src.s_addr = dev_gre->ip_local; greip->gi_i.ip_dst.s_addr = dev_gre->ip_remote; return OFP_PKT_CONTINUE; }
static int create_odp_packet_ip6(odp_packet_t *opkt, uint8_t *pkt_data, int plen) { odp_pool_t pool; odp_packet_t pkt = ODP_PACKET_INVALID; memset(orig_pkt_data, 0x0, sizeof(orig_pkt_data)); pool = odp_pool_lookup("packet_pool"); if (pool == ODP_POOL_INVALID) { fail_with_odp("ODP packet_pool not found\n"); return -1; } pkt = odp_packet_alloc(pool, plen); if (pkt == ODP_PACKET_INVALID) { fail_with_odp("ODP packet alloc failed"); return -1; } if (odp_packet_copy_from_mem(pkt, 0, plen, pkt_data) < 0) { fail_with_odp("Packet data copy failed\n"); return -1; }; odp_packet_has_eth_set(pkt, 1); odp_packet_has_l2_set(pkt, 1); odp_packet_has_ipv6_set(pkt, 1); odp_packet_l2_offset_set(pkt, 0); odp_packet_l3_offset_set(pkt, OFP_ETHER_HDR_LEN); *opkt = pkt; odp_packet_copy_to_mem(pkt, 0, plen, orig_pkt_data); return 0; }
static int create_odp_packet_ip4(odp_packet_t *opkt, uint8_t *pkt_data, int plen, uint32_t dst_addr) { odp_pool_t pool; uint8_t *buf; odp_packet_t pkt = ODP_PACKET_INVALID; struct ofp_ether_header *eth; struct ofp_ip *iphdr; uint32_t eth_len; memset(orig_pkt_data, 0x0, sizeof(orig_pkt_data)); pool = odp_pool_lookup("packet_pool"); if (pool == ODP_POOL_INVALID) { fail_with_odp("ODP packet_pool not found\n"); return -1; } pkt = odp_packet_alloc(pool, plen); if (pkt == ODP_PACKET_INVALID) { fail_with_odp("ODP packet alloc failed"); return -1; } buf = odp_packet_data(pkt); if (odp_packet_copy_from_mem(pkt, 0, plen, pkt_data) < 0) { fail_with_odp("Packet data copy failed\n"); return -1; }; iphdr = (struct ofp_ip *)&buf[OFP_ETHER_HDR_LEN]; /* changes to the default packet. Recalculate ip checksum */ if (dst_addr) { iphdr->ip_dst.s_addr = dst_addr; iphdr->ip_sum = 0; iphdr->ip_sum = ofp_cksum_buffer((uint16_t *)iphdr, iphdr->ip_hl<<2); } /* END OF changes to the default packet */ eth = (struct ofp_ether_header *)buf; if (eth->ether_type == odp_cpu_to_be_16(OFP_ETHERTYPE_VLAN)) eth_len = OFP_ETHER_HDR_LEN + OFP_ETHER_VLAN_ENCAP_LEN; else eth_len = OFP_ETHER_HDR_LEN; odp_packet_has_eth_set(pkt, 1); odp_packet_has_l2_set(pkt, 1); odp_packet_has_ipv4_set(pkt, 1); odp_packet_l2_offset_set(pkt, 0); odp_packet_l3_offset_set(pkt, eth_len); odp_packet_l4_offset_set(pkt, eth_len + (iphdr->ip_hl<<2)); *opkt = pkt; odp_packet_copy_to_mem(pkt, 0, plen, orig_pkt_data); return 0; }