enum ofp_return_code ofp_ipv6_processing(odp_packet_t *pkt) { int res; int protocol = IS_IPV6; uint32_t flags; struct ofp_ip6_hdr *ipv6; struct ofp_nh6_entry *nh; struct ofp_ifnet *dev = odp_packet_user_ptr(*pkt); int is_ours = 0; ipv6 = (struct ofp_ip6_hdr *)odp_packet_l3_ptr(*pkt, NULL); if (odp_unlikely(ipv6 == NULL)) return OFP_PKT_DROP; /* is ipv6->dst_addr one of my IPv6 addresses from this interface*/ if (ofp_ip6_equal(dev->ip6_addr, ipv6->ip6_dst.ofp_s6_addr) || OFP_IN6_IS_SOLICITED_NODE_MC(ipv6->ip6_dst, dev->ip6_addr) || (memcmp((const void *)((uintptr_t)dev->link_local + 8), (const void *)((uintptr_t)ipv6->ip6_dst.ofp_s6_addr + 8), 2 * sizeof(uint32_t)) == 0)) { is_ours = 1; } /* check if it's ours for another ipv6 address */ if (!is_ours) { nh = ofp_get_next_hop6(dev->vrf, ipv6->ip6_dst.ofp_s6_addr, &flags); if (nh && (nh->flags & OFP_RTF_LOCAL)) is_ours = 1; } if (is_ours) { OFP_HOOK(OFP_HOOK_LOCAL, *pkt, &protocol, &res); if (res != OFP_PKT_CONTINUE) { OFP_DBG("OFP_HOOK_LOCAL returned %d", res); return res; } OFP_HOOK(OFP_HOOK_LOCAL_IPv6, *pkt, NULL, &res); if (res != OFP_PKT_CONTINUE) { OFP_DBG("OFP_HOOK_LOCAL_IPv6 returned %d", res); return res; } return ipv6_transport_classifier(pkt, ipv6->ofp_ip6_nxt); } OFP_HOOK(OFP_HOOK_FWD_IPv6, *pkt, NULL, &res); if (res != OFP_PKT_CONTINUE) { OFP_DBG("OFP_HOOK_FWD_IPv6 returned %d", res); return res; } nh = ofp_get_next_hop6(dev->vrf, ipv6->ip6_dst.ofp_s6_addr, &flags); if (nh == NULL) return OFP_PKT_CONTINUE; return ofp_ip6_output(*pkt, nh); }
static void test_hook_out_ipv6(void) { int res; odp_packet_t pkt = ODP_PACKET_INVALID; if (create_odp_packet_ip6(&pkt, ip6udp_frame, sizeof(ip6udp_frame))) { CU_FAIL("Fail to create packet"); return; } my_test_val = TEST_HOOK_OUT_IPv6; res = ofp_ip6_output(pkt, NULL); my_test_val = 0; CU_ASSERT_EQUAL(res, TEST_HOOK_OUT_IPv6_VALUE); CU_PASS("test_hook_out_ipv6"); }
static void test_packet_output_ipv6_to_gre(void) { odp_packet_t pkt = ODP_PACKET_INVALID; odp_event_t ev; int res; struct ofp_ether_header *eth; struct ofp_ip6_hdr *ip6, *ip6_orig; struct ofp_ip *ip; struct ofp_greip *greip; (void)tcp_frame; (void)icmp_frame; (void)arp_frame; (void)icmp6_frame; if (create_odp_packet_ip6(&pkt, ip6udp_frame, sizeof(ip6udp_frame))) { CU_FAIL("Fail to create packet"); return; } ip6 = odp_packet_l3_ptr(pkt, NULL); ofp_set_route6_params(OFP_ROUTE6_ADD, 0 /*vrf*/, 100 /*vlan*/, GRE_PORTS, ip6->ip6_dst.__u6_addr.__u6_addr8, 64 /*masklen*/, 0 /*gw*/, OFP_RTF_NET /* flags */); res = ofp_ip6_output(pkt, NULL); CU_ASSERT_EQUAL(res, OFP_PKT_PROCESSED); res = ofp_send_pending_pkt(); CU_ASSERT_EQUAL(res, OFP_PKT_PROCESSED); ev = odp_queue_deq(dev->outq_def); CU_ASSERT_NOT_EQUAL_FATAL(ev, ODP_EVENT_INVALID); pkt = odp_packet_from_event(ev); CU_ASSERT_EQUAL_FATAL(odp_packet_len(pkt), sizeof(ip6udp_frame) + 20 + 4); eth = odp_packet_l2_ptr(pkt, NULL); if (memcmp(eth->ether_dhost, tun_rem_mac, OFP_ETHER_ADDR_LEN)) CU_FAIL("Bad destination mac address."); if (memcmp(eth->ether_shost, dev->mac, OFP_ETHER_ADDR_LEN)) CU_FAIL("Bad source mac address."); ip = odp_packet_l3_ptr(pkt, NULL); CU_ASSERT_EQUAL(ip->ip_src.s_addr, dev_ip); CU_ASSERT_EQUAL(ip->ip_dst.s_addr, tun_rem_ip); CU_ASSERT_EQUAL(ip->ip_p, OFP_IPPROTO_GRE); greip = (struct ofp_greip *)ip; CU_ASSERT_EQUAL(greip->gi_g.flags, 0); CU_ASSERT_EQUAL(greip->gi_g.ptype, odp_cpu_to_be_16(OFP_ETHERTYPE_IPV6)); /* inner ip */ ip6 = (struct ofp_ip6_hdr *)(greip + 1); ip6_orig = (struct ofp_ip6_hdr *) (&orig_pkt_data[OFP_ETHER_HDR_LEN]); if (memcmp(ip6, ip6_orig, odp_be_to_cpu_16(ip6_orig->ofp_ip6_plen) + sizeof(*ip6))) CU_FAIL("Inner IP packet error."); }