diff --git a/doc/plan.org b/doc/plan.org index a9ae98c..c951497 100644 --- a/doc/plan.org +++ b/doc/plan.org @@ -204,7 +204,69 @@ multicast address of the target address." **** DONE Make switch answer icmp6 echo request for **** TODO Make switch answer icmp echo request for **** TODO Introduce mixed mode: switch: icmp6 echo reply, controller: NDP -***** TODO try 1: reply seen, but checksum is incorrect +***** DONE try 1: reply seen, but checksum is incorrect +***** TODO try 2: analysing tagya checksumming code +static uint16_t ip6_checksum(struct ip6 *ip6, uint32_t data_len, uint8_t proto) +{ + uint32_t sum = 0; + uint16_t *p; + int i; + + for (i = 0, p = ip6->src.s6_addr16; i < 16; ++i) + sum += *p++; + sum += htonl(data_len) >> 16; + sum += htonl(data_len) & 0xffff; + sum += htons(proto); + + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} + +static uint16_t convert_cksum(struct ip6 *ip6, struct ip4 *ip4) +{ + uint32_t sum = 0; + uint16_t *p; + int i; + + sum += ~ip4->src.s_addr >> 16; + sum += ~ip4->src.s_addr & 0xffff; + sum += ~ip4->dest.s_addr >> 16; + sum += ~ip4->dest.s_addr & 0xffff; + + for (i = 0, p = ip6->src.s6_addr16; i < 16; ++i) + sum += *p++; + + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + + return sum; +} +... +static int xlate_payload_4to6(struct pkt *p, struct ip6 *ip6) +{ + uint16_t *tck; + uint16_t cksum; + + if (p->ip4->flags_offset & htons(IP4_F_MASK)) + return 0; + + switch (p->data_proto) { + case 1: + cksum = ip6_checksum(ip6, htons(p->ip4->length) - + p->header_len, 58); + cksum = ones_add(p->icmp->cksum, cksum); + if (p->icmp->type == 8) { + p->icmp->type = 128; + p->icmp->cksum = ones_add(cksum, ~(128 - 8)); + } else { + p->icmp->type = 129; + p->icmp->cksum = ones_add(cksum, ~(129 - 0)); + } + return 0; + + **** DONE Add default route for v6 hosts p4@ubuntu:~/master-thesis$ mx h1 ip -6 r sudo: unable to resolve host ubuntu diff --git a/p4src/bug1-bool.p4 b/p4src/bug1-bool.p4 new file mode 100644 index 0000000..932a575 --- /dev/null +++ b/p4src/bug1-bool.p4 @@ -0,0 +1,277 @@ +/* -*- P4_16 -*- */ +#include +#include + +#define THE_ANSWER_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING 42 /* Important constant */ +#define ROUTING_TABLE_SIZE 64 /* maximum routes per protocol */ +#define ADDRESS_TABLE_SIZE 64 /* maximum number of addresses per protocol */ +#define NDP_TABLE_SIZE 64 /* maximum number of multicast groups */ + +typedef bit<48> mac_addr_t; +typedef bit<32> ipv4_addr_t; +typedef bit<128> ipv6_addr_t; +typedef bit<9> port_t; +typedef bit<16> mcast_t; +typedef bit<16> task_t; + + +const bit<16> TYPE_IPV4 = 0x0800; +const bit<16> TYPE_IPV6 = 0x86DD; +const bit<16> TYPE_CPU = 0x4242; +const bit<16> TYPE_DEBUG = 0x2323; + + +const bit<8> PROTO_ICMP = 1; +const bit<8> PROTO_TCP = 6; +const bit<8> PROTO_UDP = 17; +const bit<8> PROTO_ICMP6 = 58; + +const bit<8> TCP_SEQ_LEN = 4; + +const bit<8> ICMP6_ECHO_REQUEST = 128; +const bit<8> ICMP6_ECHO_REPLY = 129; +const bit<8> ICMP6_NS = 135; +const bit<8> ICMP6_NA = 136; + +const task_t TASK_ICMP6_NS = 1; +const task_t TASK_ICMP6_GENERAL = 2; +const task_t TASK_DEBUG = 3; +const task_t TASK_ICMP6_REPLY = 4; + + +header ethernet_t { + mac_addr_t dst_addr; + mac_addr_t src_addr; + bit<16> ethertype; +} + +header ipv4_t { + bit<4> version; + bit<4> ihl; + bit<6> diff_serv; + bit<2> ecn; + bit<16> totalLen; + bit<16> identification; + bit<3> flags; + bit<13> fragOffset; + bit<8> ttl; + bit<8> protocol; + bit<16> hdrChecksum; + ipv4_addr_t src_addr; + ipv4_addr_t dst_addr; +} + +/* https://en.wikipedia.org/wiki/IPv6_packet */ +header ipv6_t { + bit<4> version; + bit<8> traffic_class; + bit<20> flow_label; + bit<16> payload_length; + bit<8> next_header; + bit<8> hop_limit; + ipv6_addr_t src_addr; + ipv6_addr_t dst_addr; +} + +header tcp_t{ + bit<16> src_port; + bit<16> dst_port; + int<32> seqNo; + int<32> ackNo; + bit<4> data_offset; + bit<4> res; + bit<1> cwr; + bit<1> ece; + bit<1> urg; + bit<1> ack; + bit<1> psh; + bit<1> rst; + bit<1> syn; + bit<1> fin; + bit<16> window; + bit<16> checksum; + bit<16> urgentPtr; +} + +header udp_t { + bit<16> src_port; + bit<16> dst_port; + bit<16> payload_length; + bit<16> checksum; +} + +header icmp6_t { + bit<8> type; + bit<8> code; + bit<16> checksum; +} + +header icmp_t { + bit<8> type; + bit<8> code; + bit<16> checksum; + bit<32> rest; +} + +header cpu_t { + task_t task; + bit<16> ingress_port; + bit<16> ethertype; +} + +struct headers { + ethernet_t ethernet; + ipv4_t ipv4; + ipv6_t ipv6; + tcp_t tcp; + udp_t udp; + icmp6_t icmp6; + icmp_t icmp; + cpu_t cpu; +} + +struct metadata { + bool do_cksum; +} + +parser MyParser(packet_in packet, + out headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + + state start { + packet.extract(hdr.ethernet); + transition select(hdr.ethernet.ethertype){ + TYPE_IPV4: ipv4; + TYPE_IPV6: ipv6; + default: accept; + } + } + + state ipv4 { + packet.extract(hdr.ipv4); + meta.tcp_length = hdr.ipv4.totalLen - 16w20; + + transition select(hdr.ipv4.protocol){ + PROTO_TCP: tcp; + PROTO_UDP: udp; + PROTO_ICMP: icmp; + + default: accept; + } + } + + state ipv6 { + packet.extract(hdr.ipv6); + meta.tcp_length = hdr.ipv6.payload_length; + + transition select(hdr.ipv6.next_header){ + PROTO_TCP: tcp; + PROTO_UDP: udp; + PROTO_ICMP6: icmp6; + default: accept; + } + } + + /* Leaf */ + state tcp { + packet.extract(hdr.tcp); + transition accept; + } + + state udp { + packet.extract(hdr.udp); + transition accept; + } + + state icmp6 { + packet.extract(hdr.icmp6); + transition accept; + } + + state icmp { + packet.extract(hdr.icmp); + transition accept; + } + +} + +control MyDeparser(packet_out packet, in headers hdr) { + apply { + /* always */ + packet.emit(hdr.ethernet); + + /* only if information is sent to the controller */ + packet.emit(hdr.cpu); + + /* either */ + packet.emit(hdr.ipv4); + packet.emit(hdr.ipv6); + + /* either */ + packet.emit(hdr.tcp); + packet.emit(hdr.udp); + packet.emit(hdr.icmp); + packet.emit(hdr.icmp6); + } +} + +control MyIngress(inout headers hdr, + action icmp6_echo_reply() { + meta.do_cksum = true; + } + + table v6_addresses { + key = { + hdr.ipv6.dst_addr: exact; + } + actions = { + icmp6_echo_reply; + NoAction; + } + size = ADDRESS_TABLE_SIZE; + default_action = NoAction; + } + + apply { + if(hdr.ipv6.isValid()) { + v6_addresses.apply(); + } + } +} + +control MyEgress(inout headers hdr, + inout metadata meta, + inout standard_metadata_t standard_metadata) { + apply { + } +} + +control MyVerifyChecksum(inout headers hdr, inout metadata meta) { + apply {} +} + +control MyComputeChecksum(inout headers hdr, inout metadata meta) { + apply { + update_checksum_with_payload(meta.do_cksum, + { + hdr.ipv6.src_addr, /* 128 */ + hdr.ipv6.dst_addr, /* 128 */ + meta.cast_length, /* 32 */ + 24w0, /* 24 0's */ + PROTO_ICMP6 /* 8 */ + }, + hdr.icmp6.checksum, + HashAlgorithm.csum16 + ); + } +} + +V1Switch( +MyParser(), +MyVerifyChecksum(), +MyIngress(), +MyEgress(), +MyComputeChecksum(), +MyDeparser() +) main;