/* * Copyright 2019-present GEANT RARE project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed On an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _IG_CTL_IPv6_P4_ #define _IG_CTL_IPv6_P4_ control IngressControlIPv6(inout headers hdr, inout ingress_metadata_t ig_md, inout standard_metadata_t ig_intr_md) { direct_counter(CounterType.packets_and_bytes) statsH; direct_counter(CounterType.packets_and_bytes) statsR; action send_to_cpu() { /* * Prepend cpu header to pkt sent to controller * by calling setValid() so it is tekne into account by deparser */ ig_md.nexthop_id = CPU_PORT; } action act_ipv6_cpl_set_nexthop() { /* * Send to CPU * CPU => 64 */ send_to_cpu(); } action act_ipv6_fib_discard() { mark_to_drop(ig_intr_md); } /* * Perform L3 forwarding */ action act_ipv6_set_nexthop(NextHopId_t nexthop_id) { /* * ig_md.nexthop_id is set now to the egress_port * set by the control plane entry * for further processing by ig_tm_md.ucast_egress_port */ ig_md.nexthop_id = nexthop_id; } action act_ipv6_mpls1_encap_set_nexthop(label_t egress_label, NextHopId_t nexthop_id) { /* * Egress packet is now a MPLS packet * (LABEL imposition) */ ig_md.ethertype = ETHERTYPE_MPLS_UCAST; ig_md.mpls0_remove = 0; /* * Encapsulate MPLS header * And set egress label */ hdr.mpls0.setValid(); hdr.mpls0.label = egress_label; hdr.mpls0.ttl = hdr.ipv6.hop_limit; hdr.mpls0.bos = 1; /* * Set nexthop_id for further forwarding process */ ig_md.nexthop_id = nexthop_id; } action act_ipv6_mpls2_encap_set_nexthop(label_t vpn_label, label_t egress_label, NextHopId_t nexthop_id) { /* * Egress packet is now a MPLS packet * (LABEL imposition) */ ig_md.ethertype = ETHERTYPE_MPLS_UCAST; ig_md.mpls0_remove = 0; ig_md.mpls1_remove = 0; /* * Encapsulate MPLS header * And set egress label */ hdr.mpls0.setValid(); hdr.mpls0.label = egress_label; hdr.mpls0.ttl = hdr.ipv6.hop_limit; hdr.mpls0.bos = 0; /* * MPLS VPN */ hdr.mpls1.setValid(); hdr.mpls1.label = vpn_label; hdr.mpls1.ttl = hdr.ipv6.hop_limit; hdr.mpls1.bos = 1; /* * Set nexthop_id for further forwarding process */ ig_md.nexthop_id = nexthop_id; } action act_srv_decap_ipv4(switch_vrf_t vrf) { ig_md.vrf = vrf; ig_md.srv_op_type = 4; } action act_srv_decap_ipv6(switch_vrf_t vrf) { ig_md.vrf = vrf; ig_md.srv_op_type = 6; } action act_srv_decap_evpn(SubIntId_t bridge) { ig_md.vrf = 0; ig_md.srv_op_type = 2; ig_md.bridge_id = bridge; ig_md.ethertype = hdr.eth3.ethertype; hdr.ethernet.src_mac_addr = hdr.eth3.src_mac_addr; hdr.ethernet.dst_mac_addr = hdr.eth3.dst_mac_addr; } action act_ipv6_srv_encap_set_nexthop(ipv6_addr_t target, NextHopId_t nexthop_id) { ig_md.ethertype = ETHERTYPE_IPV6; hdr.ipv6b.setValid(); hdr.ipv6b = hdr.ipv6; hdr.ipv6.version = 6; hdr.ipv6.payload_len = hdr.ipv6b.payload_len + 40; hdr.ipv6.next_hdr = IP_PROTOCOL_IPV6; hdr.ipv6.hop_limit = 255; hdr.ipv6.src_addr = target; hdr.ipv6.dst_addr = target; ig_md.nexthop_id = nexthop_id; } table tbl_ipv6_fib_host { key = { /* * we match /32 host route */ hdr.ipv6.dst_addr: exact; ig_md.vrf: exact; } actions = { act_ipv6_cpl_set_nexthop; act_ipv6_set_nexthop; act_ipv6_mpls1_encap_set_nexthop; act_ipv6_mpls2_encap_set_nexthop; act_ipv6_srv_encap_set_nexthop; act_srv_decap_ipv4; act_srv_decap_ipv6; act_srv_decap_evpn; @defaultonly NoAction; } size = IPV6_HOST_TABLE_SIZE; const default_action = NoAction(); counters = statsH; } table tbl_ipv6_fib_lpm { key = { /* * we match network route via Long Prefix Match kind operation */ hdr.ipv6.dst_addr: lpm; ig_md.vrf: exact; } actions = { act_ipv6_cpl_set_nexthop; act_ipv6_set_nexthop; act_ipv6_mpls1_encap_set_nexthop; act_ipv6_mpls2_encap_set_nexthop; act_ipv6_srv_encap_set_nexthop; act_ipv6_fib_discard; @defaultonly NoAction; } size = IPV6_LPM_TABLE_SIZE; default_action = NoAction(); counters = statsR; } apply { /* * It is a dataplane packet */ //if (hdr.ipv6.isValid() && hdr.ipv6.ttl > 1) { if (ig_md.ipv6_valid==1) { if (hdr.ipv6.next_hdr==IP_PROTOCOL_HOPOPT) { act_ipv6_cpl_set_nexthop(); return; } if (!tbl_ipv6_fib_host.apply().hit) { tbl_ipv6_fib_lpm.apply(); } } } } #endif // _IG_CTL_IPv6_P4_