tunnel.p4
Tunneling: VXLAN and NVGRE (including L2/L3 Gateway), Geneve, GRE and IPinIP
/*
Copyright 2013-present Barefoot Networks, Inc.
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.
*/
/*
* Tunnel processing
*/
/*
* Tunnel metadata
*/
header_type tunnel_metadata_t {
fields {
ingress_tunnel_type : 5; /* tunnel type from parser */
tunnel_vni : 24; /* tunnel id */
mpls_enabled : 1; /* is mpls enabled on BD */
mpls_label: 20; /* Mpls label */
mpls_exp: 3; /* Mpls Traffic Class */
mpls_ttl: 8; /* Mpls Ttl */
egress_tunnel_type : 5; /* type of tunnel */
tunnel_index: 14; /* tunnel index */
tunnel_src_index : 9; /* index to tunnel src ip */
tunnel_smac_index : 9; /* index to tunnel src mac */
tunnel_dst_index : 14; /* index to tunnel dst ip */
tunnel_dmac_index : 14; /* index to tunnel dst mac */
vnid : 24; /* tunnel vnid */
tunnel_terminate : 1; /* is tunnel being terminated? */
tunnel_if_check : 1; /* tun terminate xor originate */
egress_header_count: 4; /* number of mpls header stack */
inner_ip_proto : 8; /* Inner IP protocol */
skip_encap_inner : 1; /* skip encap_process_inner */
}
}
metadata tunnel_metadata_t tunnel_metadata;
#ifndef TUNNEL_DISABLE
/*****************************************************************************/
/* Outer router mac lookup */
/*****************************************************************************/
action outer_rmac_hit() {
modify_field(l3_metadata.rmac_hit, TRUE);
}
table outer_rmac {
reads {
l3_metadata.rmac_group : exact;
ethernet.dstAddr : exact;
}
actions {
on_miss;
outer_rmac_hit;
}
size : OUTER_ROUTER_MAC_TABLE_SIZE;
}
#endif /* TUNNEL_DISABLE */
#ifndef TUNNEL_DISABLE
/*****************************************************************************/
/* IPv4 source and destination VTEP lookups */
/*****************************************************************************/
action set_tunnel_termination_flag() {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
}
action set_tunnel_vni_and_termination_flag(tunnel_vni) {
modify_field(tunnel_metadata.tunnel_vni, tunnel_vni);
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
}
action src_vtep_hit(ifindex) {
modify_field(ingress_metadata.ifindex, ifindex);
}
#ifndef IPV4_DISABLE
table ipv4_dest_vtep {
reads {
l3_metadata.vrf : exact;
ipv4.dstAddr : exact;
tunnel_metadata.ingress_tunnel_type : exact;
}
actions {
nop;
set_tunnel_termination_flag;
set_tunnel_vni_and_termination_flag;
}
size : DEST_TUNNEL_TABLE_SIZE;
}
table ipv4_src_vtep {
reads {
l3_metadata.vrf : exact;
ipv4.srcAddr : exact;
tunnel_metadata.ingress_tunnel_type : exact;
}
actions {
on_miss;
src_vtep_hit;
}
size : IPV4_SRC_TUNNEL_TABLE_SIZE;
}
#endif /* IPV4_DISABLE */
#ifndef IPV6_DISABLE
/*****************************************************************************/
/* IPv6 source and destination VTEP lookups */
/*****************************************************************************/
table ipv6_dest_vtep {
reads {
l3_metadata.vrf : exact;
ipv6.dstAddr : exact;
tunnel_metadata.ingress_tunnel_type : exact;
}
actions {
nop;
set_tunnel_termination_flag;
set_tunnel_vni_and_termination_flag;
}
size : DEST_TUNNEL_TABLE_SIZE;
}
table ipv6_src_vtep {
reads {
l3_metadata.vrf : exact;
ipv6.srcAddr : exact;
tunnel_metadata.ingress_tunnel_type : exact;
}
actions {
on_miss;
src_vtep_hit;
}
size : IPV6_SRC_TUNNEL_TABLE_SIZE;
}
#endif /* IPV6_DISABLE */
#endif /* TUNNEL_DISABLE */
control process_ipv4_vtep {
#if !defined(TUNNEL_DISABLE) && !defined(IPV4_DISABLE)
apply(ipv4_src_vtep) {
src_vtep_hit {
apply(ipv4_dest_vtep);
}
}
#endif /* TUNNEL_DISABLE && IPV4_DISABLE */
}
control process_ipv6_vtep {
#if !defined(TUNNEL_DISABLE) && !defined(IPV6_DISABLE)
apply(ipv6_src_vtep) {
src_vtep_hit {
apply(ipv6_dest_vtep);
}
}
#endif /* TUNNEL_DISABLE && IPV6_DISABLE */
}
#ifndef TUNNEL_DISABLE
/*****************************************************************************/
/* Tunnel termination */
/*****************************************************************************/
action terminate_tunnel_inner_non_ip(bd, bd_label, stats_idx) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(ingress_metadata.bd, bd);
modify_field(acl_metadata.bd_label, bd_label);
modify_field(l2_metadata.bd_stats_idx, stats_idx);
modify_field(l3_metadata.lkp_ip_type, IPTYPE_NONE);
modify_field(l2_metadata.lkp_mac_type, inner_ethernet.etherType);
}
#ifndef IPV4_DISABLE
action terminate_tunnel_inner_ethernet_ipv4(bd, vrf,
rmac_group, bd_label,
ipv4_unicast_enabled, ipv4_urpf_mode,
igmp_snooping_enabled, stats_idx,
ipv4_multicast_enabled, mrpf_group) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(ingress_metadata.bd, bd);
modify_field(l3_metadata.vrf, vrf);
modify_field(ipv4_metadata.ipv4_unicast_enabled, ipv4_unicast_enabled);
modify_field(ipv4_metadata.ipv4_urpf_mode, ipv4_urpf_mode);
modify_field(l3_metadata.rmac_group, rmac_group);
modify_field(acl_metadata.bd_label, bd_label);
modify_field(l2_metadata.bd_stats_idx, stats_idx);
modify_field(l3_metadata.lkp_ip_type, IPTYPE_IPV4);
modify_field(l2_metadata.lkp_mac_type, inner_ethernet.etherType);
modify_field(l3_metadata.lkp_ip_version, inner_ipv4.version);
#ifdef QOS_DISABLE
modify_field(l3_metadata.lkp_dscp, inner_ipv4.diffserv);
#endif /* QOS_DISABLE */
modify_field(multicast_metadata.igmp_snooping_enabled,
igmp_snooping_enabled);
modify_field(multicast_metadata.ipv4_multicast_enabled,
ipv4_multicast_enabled);
modify_field(multicast_metadata.bd_mrpf_group, mrpf_group);
}
action terminate_tunnel_inner_ipv4(vrf, rmac_group,
ipv4_urpf_mode, ipv4_unicast_enabled,
ipv4_multicast_enabled, mrpf_group) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(l3_metadata.vrf, vrf);
modify_field(ipv4_metadata.ipv4_unicast_enabled, ipv4_unicast_enabled);
modify_field(ipv4_metadata.ipv4_urpf_mode, ipv4_urpf_mode);
modify_field(l3_metadata.rmac_group, rmac_group);
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
modify_field(l3_metadata.lkp_ip_type, IPTYPE_IPV4);
modify_field(l3_metadata.lkp_ip_version, inner_ipv4.version);
#ifdef QOS_DISABLE
modify_field(l3_metadata.lkp_dscp, inner_ipv4.diffserv);
#endif /* QOS_DISABLE */
modify_field(multicast_metadata.bd_mrpf_group, mrpf_group);
modify_field(multicast_metadata.ipv4_multicast_enabled,
ipv4_multicast_enabled);
}
#endif /* IPV4_DISABLE */
#ifndef IPV6_DISABLE
action terminate_tunnel_inner_ethernet_ipv6(bd, vrf,
rmac_group, bd_label,
ipv6_unicast_enabled, ipv6_urpf_mode,
mld_snooping_enabled, stats_idx,
ipv6_multicast_enabled, mrpf_group) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(ingress_metadata.bd, bd);
modify_field(l3_metadata.vrf, vrf);
modify_field(ipv6_metadata.ipv6_unicast_enabled, ipv6_unicast_enabled);
modify_field(ipv6_metadata.ipv6_urpf_mode, ipv6_urpf_mode);
modify_field(l3_metadata.rmac_group, rmac_group);
modify_field(acl_metadata.bd_label, bd_label);
modify_field(l2_metadata.bd_stats_idx, stats_idx);
modify_field(l3_metadata.lkp_ip_type, IPTYPE_IPV6);
modify_field(l2_metadata.lkp_mac_type, inner_ethernet.etherType);
modify_field(l3_metadata.lkp_ip_version, inner_ipv6.version);
#ifdef QOS_DISABLE
modify_field(l3_metadata.lkp_dscp, inner_ipv6.trafficClass);
#endif /* QOS_DISABLE */
modify_field(multicast_metadata.bd_mrpf_group, mrpf_group);
modify_field(multicast_metadata.ipv6_multicast_enabled,
ipv6_multicast_enabled);
modify_field(multicast_metadata.mld_snooping_enabled, mld_snooping_enabled);
}
action terminate_tunnel_inner_ipv6(vrf, rmac_group,
ipv6_unicast_enabled, ipv6_urpf_mode,
ipv6_multicast_enabled, mrpf_group) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(l3_metadata.vrf, vrf);
modify_field(ipv6_metadata.ipv6_unicast_enabled, ipv6_unicast_enabled);
modify_field(ipv6_metadata.ipv6_urpf_mode, ipv6_urpf_mode);
modify_field(l3_metadata.rmac_group, rmac_group);
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
modify_field(l3_metadata.lkp_ip_type, IPTYPE_IPV6);
modify_field(l3_metadata.lkp_ip_version, inner_ipv6.version);
#ifdef QOS_DISABLE
modify_field(l3_metadata.lkp_dscp, inner_ipv6.trafficClass);
#endif /* QOS_DISABLE */
modify_field(multicast_metadata.bd_mrpf_group, mrpf_group);
modify_field(multicast_metadata.ipv6_multicast_enabled,
ipv6_multicast_enabled);
}
#endif /* IPV6_DISABLE */
action tunnel_lookup_miss() {
}
table tunnel {
reads {
tunnel_metadata.tunnel_vni : exact;
tunnel_metadata.ingress_tunnel_type : exact;
inner_ipv4 : valid;
inner_ipv6 : valid;
}
actions {
nop;
tunnel_lookup_miss;
terminate_tunnel_inner_non_ip;
#ifndef IPV4_DISABLE
terminate_tunnel_inner_ethernet_ipv4;
terminate_tunnel_inner_ipv4;
#endif /* IPV4_DISABLE */
#ifndef IPV6_DISABLE
terminate_tunnel_inner_ethernet_ipv6;
terminate_tunnel_inner_ipv6;
#endif /* IPV6_DISABLE */
}
size : VNID_MAPPING_TABLE_SIZE;
}
#endif /* TUNNEL_DISABLE */
action ipv4_lkp() {
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
modify_field(ipv4_metadata.lkp_ipv4_sa, ipv4.srcAddr);
modify_field(ipv4_metadata.lkp_ipv4_da, ipv4.dstAddr);
modify_field(l3_metadata.lkp_ip_proto, ipv4.protocol);
modify_field(l3_metadata.lkp_ip_ttl, ipv4.ttl);
modify_field(l3_metadata.lkp_l4_sport, l3_metadata.lkp_outer_l4_sport);
modify_field(l3_metadata.lkp_l4_dport, l3_metadata.lkp_outer_l4_dport);
modify_field(intrinsic_metadata.mcast_grp, 0);
}
action ipv6_lkp() {
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
modify_field(ipv6_metadata.lkp_ipv6_sa, ipv6.srcAddr);
modify_field(ipv6_metadata.lkp_ipv6_da, ipv6.dstAddr);
modify_field(l3_metadata.lkp_ip_proto, ipv6.nextHdr);
modify_field(l3_metadata.lkp_ip_ttl, ipv6.hopLimit);
modify_field(l3_metadata.lkp_l4_sport, l3_metadata.lkp_outer_l4_sport);
modify_field(l3_metadata.lkp_l4_dport, l3_metadata.lkp_outer_l4_dport);
modify_field(intrinsic_metadata.mcast_grp, 0);
}
action non_ip_lkp() {
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
modify_field(intrinsic_metadata.mcast_grp, 0);
}
table adjust_lkp_fields {
reads {
ipv4 : valid;
ipv6 : valid;
}
actions {
non_ip_lkp;
ipv4_lkp;
#ifndef IPV6_DISABLE
ipv6_lkp;
#endif /* IPV6_DISABLE */
}
}
table tunnel_lookup_miss {
reads {
ipv4 : valid;
ipv6 : valid;
}
actions {
non_ip_lkp;
ipv4_lkp;
#ifndef IPV6_DISABLE
ipv6_lkp;
#endif /* IPV6_DISABLE */
}
}
/*****************************************************************************/
/* Ingress tunnel processing */
/*****************************************************************************/
control process_tunnel {
/* ingress fabric processing */
process_ingress_fabric();
#ifndef TUNNEL_DISABLE
if (tunnel_metadata.ingress_tunnel_type != INGRESS_TUNNEL_TYPE_NONE) {
/* outer RMAC lookup for tunnel termination */
apply(outer_rmac) {
on_miss {
process_outer_multicast();
}
default {
if (valid(ipv4)) {
process_ipv4_vtep();
} else {
if (valid(ipv6)) {
process_ipv6_vtep();
} else {
/* check for mpls tunnel termination */
#ifndef MPLS_DISABLE
if (valid(mpls[0])) {
process_mpls();
}
#endif
}
}
}
}
}
/* perform tunnel termination */
if ((tunnel_metadata.tunnel_terminate == TRUE) or
((multicast_metadata.outer_mcast_route_hit == TRUE) and
(((multicast_metadata.outer_mcast_mode == MCAST_MODE_SM) and
(multicast_metadata.mcast_rpf_group == 0)) or
((multicast_metadata.outer_mcast_mode == MCAST_MODE_BIDIR) and
(multicast_metadata.mcast_rpf_group != 0))))) {
apply(tunnel) {
tunnel_lookup_miss {
apply(tunnel_lookup_miss);
}
}
} else {
apply(adjust_lkp_fields);
}
#endif /* TUNNEL_DISABLE */
}
#if !defined(TUNNEL_DISABLE) && !defined(MPLS_DISABLE)
/*****************************************************************************/
/* Validate MPLS header */
/*****************************************************************************/
action set_valid_mpls_label1() {
modify_field(tunnel_metadata.mpls_label, mpls[0].label);
modify_field(tunnel_metadata.mpls_exp, mpls[0].exp);
}
action set_valid_mpls_label2() {
modify_field(tunnel_metadata.mpls_label, mpls[1].label);
modify_field(tunnel_metadata.mpls_exp, mpls[1].exp);
}
action set_valid_mpls_label3() {
modify_field(tunnel_metadata.mpls_label, mpls[2].label);
modify_field(tunnel_metadata.mpls_exp, mpls[2].exp);
}
table validate_mpls_packet {
reads {
mpls[0].label : ternary;
mpls[0].bos : ternary;
mpls[0] : valid;
mpls[1].label : ternary;
mpls[1].bos : ternary;
mpls[1] : valid;
mpls[2].label : ternary;
mpls[2].bos : ternary;
mpls[2] : valid;
}
actions {
set_valid_mpls_label1;
set_valid_mpls_label2;
set_valid_mpls_label3;
//TODO: Redirect to cpu if more than 5 labels
}
size : VALIDATE_MPLS_TABLE_SIZE;
}
#endif /* TUNNEL_DISABLE && MPLS_DISABLE */
control validate_mpls_header {
#if !defined(TUNNEL_DISABLE) && !defined(MPLS_DISABLE)
apply(validate_mpls_packet);
#endif /* TUNNEL_DISABLE && MPLS_DISABLE */
}
#if !defined(TUNNEL_DISABLE) && !defined(MPLS_DISABLE)
/*****************************************************************************/
/* MPLS lookup/forwarding */
/*****************************************************************************/
action terminate_eompls(bd, tunnel_type) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(tunnel_metadata.ingress_tunnel_type, tunnel_type);
modify_field(ingress_metadata.bd, bd);
modify_field(l2_metadata.lkp_mac_type, inner_ethernet.etherType);
}
action terminate_vpls(bd, tunnel_type) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(tunnel_metadata.ingress_tunnel_type, tunnel_type);
modify_field(ingress_metadata.bd, bd);
modify_field(l2_metadata.lkp_mac_type, inner_ethernet.etherType);
}
#ifndef IPV4_DISABLE
action terminate_ipv4_over_mpls(vrf, tunnel_type) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(tunnel_metadata.ingress_tunnel_type, tunnel_type);
modify_field(l3_metadata.vrf, vrf);
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
modify_field(l3_metadata.lkp_ip_type, IPTYPE_IPV4);
modify_field(l2_metadata.lkp_mac_type, inner_ethernet.etherType);
modify_field(l3_metadata.lkp_ip_version, inner_ipv4.version);
#ifdef QOS_DISABLE
modify_field(l3_metadata.lkp_dscp, inner_ipv4.diffserv);
#endif /* QOS_DISABLE */
}
#endif /* IPV4_DISABLE */
#ifndef IPV6_DISABLE
action terminate_ipv6_over_mpls(vrf, tunnel_type) {
modify_field(tunnel_metadata.tunnel_terminate, TRUE);
modify_field(tunnel_metadata.ingress_tunnel_type, tunnel_type);
modify_field(l3_metadata.vrf, vrf);
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
modify_field(l3_metadata.lkp_ip_type, IPTYPE_IPV6);
modify_field(l2_metadata.lkp_mac_type, inner_ethernet.etherType);
modify_field(l3_metadata.lkp_ip_version, inner_ipv6.version);
#ifdef QOS_DISABLE
modify_field(l3_metadata.lkp_dscp, inner_ipv6.trafficClass);
#endif /* QOS_DISABLE */
}
#endif /* IPV6_DISABLE */
action terminate_pw(ifindex) {
modify_field(ingress_metadata.egress_ifindex, ifindex);
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
}
action forward_mpls(nexthop_index) {
modify_field(l3_metadata.fib_nexthop, nexthop_index);
modify_field(l3_metadata.fib_nexthop_type, NEXTHOP_TYPE_SIMPLE);
modify_field(l3_metadata.fib_hit, TRUE);
modify_field(l2_metadata.lkp_mac_sa, ethernet.srcAddr);
modify_field(l2_metadata.lkp_mac_da, ethernet.dstAddr);
}
table mpls {
reads {
tunnel_metadata.mpls_label: exact;
inner_ipv4: valid;
inner_ipv6: valid;
}
actions {
terminate_eompls;
terminate_vpls;
#ifndef IPV4_DISABLE
terminate_ipv4_over_mpls;
#endif /* IPV4_DISABLE */
#ifndef IPV6_DISABLE
terminate_ipv6_over_mpls;
#endif /* IPV6_DISABLE */
terminate_pw;
forward_mpls;
}
size : MPLS_TABLE_SIZE;
}
#endif /* TUNNEL_DISABLE && MPLS_DISABLE */
control process_mpls {
#if !defined(TUNNEL_DISABLE) && !defined(MPLS_DISABLE)
apply(mpls);
#endif /* TUNNEL_DISABLE && MPLS_DISABLE */
}
#ifndef TUNNEL_DISABLE
/*****************************************************************************/
/* Tunnel decap (strip tunnel header) */
/*****************************************************************************/
action decap_vxlan_inner_ipv4() {
copy_header(ethernet, inner_ethernet);
copy_header(ipv4, inner_ipv4);
remove_header(vxlan);
remove_header(ipv6);
remove_header(inner_ethernet);
remove_header(inner_ipv4);
}
action decap_vxlan_inner_ipv6() {
copy_header(ethernet, inner_ethernet);
copy_header(ipv6, inner_ipv6);
remove_header(vxlan);
remove_header(ipv4);
remove_header(inner_ethernet);
remove_header(inner_ipv6);
}
action decap_vxlan_inner_non_ip() {
copy_header(ethernet, inner_ethernet);
remove_header(vxlan);
remove_header(ipv4);
remove_header(ipv6);
}
action decap_genv_inner_ipv4() {
copy_header(ethernet, inner_ethernet);
copy_header(ipv4, inner_ipv4);
remove_header(genv);
remove_header(ipv6);
remove_header(inner_ethernet);
remove_header(inner_ipv4);
}
action decap_genv_inner_ipv6() {
copy_header(ethernet, inner_ethernet);
copy_header(ipv6, inner_ipv6);
remove_header(genv);
remove_header(ipv4);
remove_header(inner_ethernet);
remove_header(inner_ipv6);
}
action decap_genv_inner_non_ip() {
copy_header(ethernet, inner_ethernet);
remove_header(genv);
remove_header(ipv4);
remove_header(ipv6);
}
#ifndef NVGRE_DISABLE
action decap_nvgre_inner_ipv4() {
copy_header(ethernet, inner_ethernet);
copy_header(ipv4, inner_ipv4);
remove_header(nvgre);
remove_header(gre);
remove_header(ipv6);
remove_header(inner_ethernet);
remove_header(inner_ipv4);
}
action decap_nvgre_inner_ipv6() {
copy_header(ethernet, inner_ethernet);
copy_header(ipv6, inner_ipv6);
remove_header(nvgre);
remove_header(gre);
remove_header(ipv4);
remove_header(inner_ethernet);
remove_header(inner_ipv6);
}
action decap_nvgre_inner_non_ip() {
copy_header(ethernet, inner_ethernet);
remove_header(nvgre);
remove_header(gre);
remove_header(ipv4);
remove_header(ipv6);
}
#endif
action decap_gre_inner_ipv4() {
copy_header(ipv4, inner_ipv4);
remove_header(gre);
remove_header(ipv6);
remove_header(inner_ipv4);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action decap_gre_inner_ipv6() {
copy_header(ipv6, inner_ipv6);
remove_header(gre);
remove_header(ipv4);
remove_header(inner_ipv6);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
action decap_gre_inner_non_ip() {
modify_field(ethernet.etherType, gre.proto);
remove_header(gre);
remove_header(ipv4);
remove_header(inner_ipv6);
}
action decap_ip_inner_ipv4() {
copy_header(ipv4, inner_ipv4);
remove_header(ipv6);
remove_header(inner_ipv4);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action decap_ip_inner_ipv6() {
copy_header(ipv6, inner_ipv6);
remove_header(ipv4);
remove_header(inner_ipv6);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
#ifndef MPLS_DISABLE
action decap_mpls_inner_ipv4_pop1() {
remove_header(mpls[0]);
copy_header(ipv4, inner_ipv4);
remove_header(inner_ipv4);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action decap_mpls_inner_ipv6_pop1() {
remove_header(mpls[0]);
copy_header(ipv6, inner_ipv6);
remove_header(inner_ipv6);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
action decap_mpls_inner_ethernet_ipv4_pop1() {
remove_header(mpls[0]);
copy_header(ethernet, inner_ethernet);
copy_header(ipv4, inner_ipv4);
remove_header(inner_ethernet);
remove_header(inner_ipv4);
}
action decap_mpls_inner_ethernet_ipv6_pop1() {
remove_header(mpls[0]);
copy_header(ethernet, inner_ethernet);
copy_header(ipv6, inner_ipv6);
remove_header(inner_ethernet);
remove_header(inner_ipv6);
}
action decap_mpls_inner_ethernet_non_ip_pop1() {
remove_header(mpls[0]);
copy_header(ethernet, inner_ethernet);
remove_header(inner_ethernet);
}
action decap_mpls_inner_ipv4_pop2() {
remove_header(mpls[0]);
remove_header(mpls[1]);
copy_header(ipv4, inner_ipv4);
remove_header(inner_ipv4);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action decap_mpls_inner_ipv6_pop2() {
remove_header(mpls[0]);
remove_header(mpls[1]);
copy_header(ipv6, inner_ipv6);
remove_header(inner_ipv6);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
action decap_mpls_inner_ethernet_ipv4_pop2() {
remove_header(mpls[0]);
remove_header(mpls[1]);
copy_header(ethernet, inner_ethernet);
copy_header(ipv4, inner_ipv4);
remove_header(inner_ethernet);
remove_header(inner_ipv4);
}
action decap_mpls_inner_ethernet_ipv6_pop2() {
remove_header(mpls[0]);
remove_header(mpls[1]);
copy_header(ethernet, inner_ethernet);
copy_header(ipv6, inner_ipv6);
remove_header(inner_ethernet);
remove_header(inner_ipv6);
}
action decap_mpls_inner_ethernet_non_ip_pop2() {
remove_header(mpls[0]);
remove_header(mpls[1]);
copy_header(ethernet, inner_ethernet);
remove_header(inner_ethernet);
}
action decap_mpls_inner_ipv4_pop3() {
remove_header(mpls[0]);
remove_header(mpls[1]);
remove_header(mpls[2]);
copy_header(ipv4, inner_ipv4);
remove_header(inner_ipv4);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action decap_mpls_inner_ipv6_pop3() {
remove_header(mpls[0]);
remove_header(mpls[1]);
remove_header(mpls[2]);
copy_header(ipv6, inner_ipv6);
remove_header(inner_ipv6);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
action decap_mpls_inner_ethernet_ipv4_pop3() {
remove_header(mpls[0]);
remove_header(mpls[1]);
remove_header(mpls[2]);
copy_header(ethernet, inner_ethernet);
copy_header(ipv4, inner_ipv4);
remove_header(inner_ethernet);
remove_header(inner_ipv4);
}
action decap_mpls_inner_ethernet_ipv6_pop3() {
remove_header(mpls[0]);
remove_header(mpls[1]);
remove_header(mpls[2]);
copy_header(ethernet, inner_ethernet);
copy_header(ipv6, inner_ipv6);
remove_header(inner_ethernet);
remove_header(inner_ipv6);
}
action decap_mpls_inner_ethernet_non_ip_pop3() {
remove_header(mpls[0]);
remove_header(mpls[1]);
remove_header(mpls[2]);
copy_header(ethernet, inner_ethernet);
remove_header(inner_ethernet);
}
#endif /* MPLS_DISABLE */
table tunnel_decap_process_outer {
reads {
tunnel_metadata.ingress_tunnel_type : exact;
inner_ipv4 : valid;
inner_ipv6 : valid;
}
actions {
decap_vxlan_inner_ipv4;
decap_vxlan_inner_ipv6;
decap_vxlan_inner_non_ip;
decap_genv_inner_ipv4;
decap_genv_inner_ipv6;
decap_genv_inner_non_ip;
#ifndef NVGRE_DISABLE
decap_nvgre_inner_ipv4;
decap_nvgre_inner_ipv6;
decap_nvgre_inner_non_ip;
#endif
decap_gre_inner_ipv4;
decap_gre_inner_ipv6;
decap_gre_inner_non_ip;
decap_ip_inner_ipv4;
decap_ip_inner_ipv6;
#ifndef MPLS_DISABLE
decap_mpls_inner_ipv4_pop1;
decap_mpls_inner_ipv6_pop1;
decap_mpls_inner_ethernet_ipv4_pop1;
decap_mpls_inner_ethernet_ipv6_pop1;
decap_mpls_inner_ethernet_non_ip_pop1;
decap_mpls_inner_ipv4_pop2;
decap_mpls_inner_ipv6_pop2;
decap_mpls_inner_ethernet_ipv4_pop2;
decap_mpls_inner_ethernet_ipv6_pop2;
decap_mpls_inner_ethernet_non_ip_pop2;
decap_mpls_inner_ipv4_pop3;
decap_mpls_inner_ipv6_pop3;
decap_mpls_inner_ethernet_ipv4_pop3;
decap_mpls_inner_ethernet_ipv6_pop3;
decap_mpls_inner_ethernet_non_ip_pop3;
#endif /* MPLS_DISABLE */
}
size : TUNNEL_DECAP_TABLE_SIZE;
}
/*****************************************************************************/
/* Tunnel decap (move inner header to outer) */
/*****************************************************************************/
action decap_inner_udp() {
copy_header(udp, inner_udp);
remove_header(inner_udp);
}
action decap_inner_tcp() {
copy_tcp_header(tcp, inner_tcp);
remove_header(inner_tcp);
remove_header(udp);
}
action decap_inner_icmp() {
copy_header(icmp, inner_icmp);
remove_header(inner_icmp);
remove_header(udp);
}
action decap_inner_unknown() {
remove_header(udp);
}
table tunnel_decap_process_inner {
reads {
inner_tcp : valid;
inner_udp : valid;
inner_icmp : valid;
}
actions {
decap_inner_udp;
decap_inner_tcp;
decap_inner_icmp;
decap_inner_unknown;
}
size : TUNNEL_DECAP_TABLE_SIZE;
}
#endif /* TUNNEL_DISABLE */
/*****************************************************************************/
/* Tunnel decap processing */
/*****************************************************************************/
control process_tunnel_decap {
#ifndef TUNNEL_DISABLE
if (tunnel_metadata.tunnel_terminate == TRUE) {
if ((multicast_metadata.inner_replica == TRUE) or
(multicast_metadata.replica == FALSE)) {
apply(tunnel_decap_process_outer);
apply(tunnel_decap_process_inner);
}
}
#endif /* TUNNEL_DISABLE */
}
#ifndef TUNNEL_DISABLE
/*****************************************************************************/
/* Egress tunnel VNI lookup */
/*****************************************************************************/
action set_egress_tunnel_vni(vnid) {
modify_field(tunnel_metadata.vnid, vnid);
}
table egress_vni {
reads {
egress_metadata.bd : exact;
tunnel_metadata.egress_tunnel_type: exact;
}
actions {
nop;
set_egress_tunnel_vni;
}
size: EGRESS_VNID_MAPPING_TABLE_SIZE;
}
/*****************************************************************************/
/* Tunnel encap (inner header rewrite) */
/*****************************************************************************/
action inner_ipv4_udp_rewrite() {
copy_header(inner_ipv4, ipv4);
copy_header(inner_udp, udp);
modify_field(egress_metadata.payload_length, ipv4.totalLen);
remove_header(udp);
remove_header(ipv4);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV4);
}
action inner_ipv4_tcp_rewrite() {
copy_header(inner_ipv4, ipv4);
copy_tcp_header(inner_tcp, tcp);
modify_field(egress_metadata.payload_length, ipv4.totalLen);
remove_header(tcp);
remove_header(ipv4);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV4);
}
action inner_ipv4_icmp_rewrite() {
copy_header(inner_ipv4, ipv4);
copy_header(inner_icmp, icmp);
modify_field(egress_metadata.payload_length, ipv4.totalLen);
remove_header(icmp);
remove_header(ipv4);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV4);
}
action inner_ipv4_unknown_rewrite() {
copy_header(inner_ipv4, ipv4);
modify_field(egress_metadata.payload_length, ipv4.totalLen);
remove_header(ipv4);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV4);
}
action inner_ipv6_udp_rewrite() {
copy_header(inner_ipv6, ipv6);
copy_header(inner_udp, udp);
add(egress_metadata.payload_length, ipv6.payloadLen, 40);
remove_header(ipv6);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV6);
}
action inner_ipv6_tcp_rewrite() {
copy_header(inner_ipv6, ipv6);
copy_tcp_header(inner_tcp, tcp);
add(egress_metadata.payload_length, ipv6.payloadLen, 40);
remove_header(tcp);
remove_header(ipv6);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV6);
}
action inner_ipv6_icmp_rewrite() {
copy_header(inner_ipv6, ipv6);
copy_header(inner_icmp, icmp);
add(egress_metadata.payload_length, ipv6.payloadLen, 40);
remove_header(icmp);
remove_header(ipv6);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV6);
}
action inner_ipv6_unknown_rewrite() {
copy_header(inner_ipv6, ipv6);
add(egress_metadata.payload_length, ipv6.payloadLen, 40);
remove_header(ipv6);
modify_field(tunnel_metadata.inner_ip_proto, IP_PROTOCOLS_IPV6);
}
action inner_non_ip_rewrite() {
add(egress_metadata.payload_length, standard_metadata.packet_length, -14);
}
table tunnel_encap_process_inner {
reads {
ipv4 : valid;
ipv6 : valid;
tcp : valid;
udp : valid;
icmp : valid;
}
actions {
inner_ipv4_udp_rewrite;
inner_ipv4_tcp_rewrite;
inner_ipv4_icmp_rewrite;
inner_ipv4_unknown_rewrite;
inner_ipv6_udp_rewrite;
inner_ipv6_tcp_rewrite;
inner_ipv6_icmp_rewrite;
inner_ipv6_unknown_rewrite;
inner_non_ip_rewrite;
}
size : TUNNEL_HEADER_TABLE_SIZE;
}
/*****************************************************************************/
/* Tunnel encap (insert tunnel header) */
/*****************************************************************************/
action f_insert_vxlan_header() {
copy_header(inner_ethernet, ethernet);
add_header(udp);
add_header(vxlan);
modify_field(udp.srcPort, hash_metadata.entropy_hash);
modify_field(udp.dstPort, UDP_PORT_VXLAN);
modify_field(udp.checksum, 0);
add(udp.length_, egress_metadata.payload_length, 30);
modify_field(vxlan.flags, 0x8);
modify_field(vxlan.reserved, 0);
modify_field(vxlan.vni, tunnel_metadata.vnid);
modify_field(vxlan.reserved2, 0);
}
action ipv4_vxlan_rewrite() {
f_insert_vxlan_header();
f_insert_ipv4_header(IP_PROTOCOLS_UDP);
add(ipv4.totalLen, egress_metadata.payload_length, 50);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action ipv6_vxlan_rewrite() {
f_insert_vxlan_header();
f_insert_ipv6_header(IP_PROTOCOLS_UDP);
add(ipv6.payloadLen, egress_metadata.payload_length, 30);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
action f_insert_genv_header() {
copy_header(inner_ethernet, ethernet);
add_header(udp);
add_header(genv);
modify_field(udp.srcPort, hash_metadata.entropy_hash);
modify_field(udp.dstPort, UDP_PORT_GENV);
modify_field(udp.checksum, 0);
add(udp.length_, egress_metadata.payload_length, 30);
modify_field(genv.ver, 0);
modify_field(genv.oam, 0);
modify_field(genv.critical, 0);
modify_field(genv.optLen, 0);
modify_field(genv.protoType, ETHERTYPE_ETHERNET);
modify_field(genv.vni, tunnel_metadata.vnid);
modify_field(genv.reserved, 0);
modify_field(genv.reserved2, 0);
}
action ipv4_genv_rewrite() {
f_insert_genv_header();
f_insert_ipv4_header(IP_PROTOCOLS_UDP);
add(ipv4.totalLen, egress_metadata.payload_length, 50);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action ipv6_genv_rewrite() {
f_insert_genv_header();
f_insert_ipv6_header(IP_PROTOCOLS_UDP);
add(ipv6.payloadLen, egress_metadata.payload_length, 30);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
#ifndef NVGRE_DISABLE
action f_insert_nvgre_header() {
copy_header(inner_ethernet, ethernet);
add_header(gre);
add_header(nvgre);
modify_field(gre.proto, ETHERTYPE_ETHERNET);
modify_field(gre.recurse, 0);
modify_field(gre.flags, 0);
modify_field(gre.ver, 0);
modify_field(gre.R, 0);
modify_field(gre.K, 1);
modify_field(gre.C, 0);
modify_field(gre.S, 0);
modify_field(gre.s, 0);
modify_field(nvgre.tni, tunnel_metadata.vnid);
modify_field(nvgre.flow_id, hash_metadata.entropy_hash, 0xFF);
}
action ipv4_nvgre_rewrite() {
f_insert_nvgre_header();
f_insert_ipv4_header(IP_PROTOCOLS_GRE);
add(ipv4.totalLen, egress_metadata.payload_length, 42);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action ipv6_nvgre_rewrite() {
f_insert_nvgre_header();
f_insert_ipv6_header(IP_PROTOCOLS_GRE);
add(ipv6.payloadLen, egress_metadata.payload_length, 22);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
#endif
action f_insert_gre_header() {
add_header(gre);
}
action ipv4_gre_rewrite() {
f_insert_gre_header();
modify_field(gre.proto, ethernet.etherType);
f_insert_ipv4_header(IP_PROTOCOLS_GRE);
add(ipv4.totalLen, egress_metadata.payload_length, 24);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action ipv6_gre_rewrite() {
f_insert_gre_header();
modify_field(gre.proto, ethernet.etherType);
f_insert_ipv6_header(IP_PROTOCOLS_GRE);
add(ipv6.payloadLen, egress_metadata.payload_length, 4);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
action ipv4_ip_rewrite() {
f_insert_ipv4_header(tunnel_metadata.inner_ip_proto);
add(ipv4.totalLen, egress_metadata.payload_length, 20);
modify_field(ethernet.etherType, ETHERTYPE_IPV4);
}
action ipv6_ip_rewrite() {
f_insert_ipv6_header(tunnel_metadata.inner_ip_proto);
modify_field(ipv6.payloadLen, egress_metadata.payload_length);
modify_field(ethernet.etherType, ETHERTYPE_IPV6);
}
#ifndef MPLS_DISABLE
action mpls_ethernet_push1_rewrite() {
copy_header(inner_ethernet, ethernet);
push(mpls, 1);
modify_field(ethernet.etherType, ETHERTYPE_MPLS);
}
action mpls_ip_push1_rewrite() {
push(mpls, 1);
modify_field(ethernet.etherType, ETHERTYPE_MPLS);
}
action mpls_ethernet_push2_rewrite() {
copy_header(inner_ethernet, ethernet);
push(mpls, 2);
modify_field(ethernet.etherType, ETHERTYPE_MPLS);
}
action mpls_ip_push2_rewrite() {
push(mpls, 2);
modify_field(ethernet.etherType, ETHERTYPE_MPLS);
}
action mpls_ethernet_push3_rewrite() {
copy_header(inner_ethernet, ethernet);
push(mpls, 3);
modify_field(ethernet.etherType, ETHERTYPE_MPLS);
}
action mpls_ip_push3_rewrite() {
push(mpls, 3);
modify_field(ethernet.etherType, ETHERTYPE_MPLS);
}
#endif /* MPLS_DISABLE */
#endif /* TUNNEL_DISABLE */
#if !defined(TUNNEL_DISABLE) || !defined(MIRROR_DISABLE)
action f_insert_ipv4_header(proto) {
add_header(ipv4);
modify_field(ipv4.protocol, proto);
modify_field(ipv4.ttl, 64);
modify_field(ipv4.version, 0x4);
modify_field(ipv4.ihl, 0x5);
modify_field(ipv4.identification, 0);
}
action f_insert_ipv6_header(proto) {
add_header(ipv6);
modify_field(ipv6.version, 0x6);
modify_field(ipv6.nextHdr, proto);
modify_field(ipv6.hopLimit, 64);
modify_field(ipv6.trafficClass, 0);
modify_field(ipv6.flowLabel, 0);
}
#endif /* !TUNNEL_DISABLE || !MIRROR_DISABLE*/
#ifndef MIRROR_DISABLE
action f_insert_erspan_common_header() {
copy_header(inner_ethernet, ethernet);
add_header(gre);
add_header(erspan_t3_header);
modify_field(gre.C, 0);
modify_field(gre.R, 0);
modify_field(gre.K, 0);
modify_field(gre.S, 0);
modify_field(gre.s, 0);
modify_field(gre.recurse, 0);
modify_field(gre.flags, 0);
modify_field(gre.ver, 0);
modify_field(gre.proto, GRE_PROTOCOLS_ERSPAN_T3);
modify_field(erspan_t3_header.timestamp, i2e_metadata.ingress_tstamp);
modify_field(erspan_t3_header.span_id, i2e_metadata.mirror_session_id);
modify_field(erspan_t3_header.version, 2);
modify_field(erspan_t3_header.sgt, 0);
}
action f_insert_erspan_t3_header() {
f_insert_erspan_common_header();
}
action ipv4_erspan_t3_rewrite() {
f_insert_erspan_t3_header();
f_insert_ipv4_header(IP_PROTOCOLS_GRE);
add(ipv4.totalLen, egress_metadata.payload_length, 50);
}
action ipv6_erspan_t3_rewrite() {
f_insert_erspan_t3_header();
f_insert_ipv6_header(IP_PROTOCOLS_GRE);
add(ipv6.payloadLen, egress_metadata.payload_length, 26);
}
#ifdef NEGATIVE_MIRRORING_ENABLE
action f_insert_erspan_negative_mirroring_header() {
f_insert_erspan_common_header();
add_header(erspan_platform_subheader);
modify_field(erspan_t3_header.ft_d_other, 1);
modify_field_with_hash_based_offset(erspan_platform_subheader.neg_mirror, 0,
calc_neg_mirror, 0x100000000);
modify_field(erspan_platform_subheader.switch_id,
global_config_metadata.switch_id);
}
action ipv4_erspan_nm_rewrite() {
f_insert_erspan_negative_mirroring_header();
f_insert_ipv4_header(IP_PROTOCOLS_GRE);
add(ipv4.totalLen, egress_metadata.payload_length, 58);
}
action ipv6_erspan_nm_rewrite() {
f_insert_erspan_negative_mirroring_header();
f_insert_ipv6_header(IP_PROTOCOLS_GRE);
add(ipv6.payloadLen, egress_metadata.payload_length, 34);
}
#endif /* NEGATIVE_MIRRORING_ENABLE */
#endif /* MIRROR_DISABLE */
table tunnel_encap_process_outer {
reads {
tunnel_metadata.egress_tunnel_type : exact;
tunnel_metadata.egress_header_count : exact;
multicast_metadata.replica : exact;
}
actions {
nop;
fabric_rewrite;
#ifndef TUNNEL_DISABLE
ipv4_vxlan_rewrite;
ipv4_genv_rewrite;
#ifndef NVGRE_DISABLE
ipv4_nvgre_rewrite;
#endif /* NVGRE_DISABLE */
ipv4_gre_rewrite;
ipv4_ip_rewrite;
#ifndef TUNNEL_OVER_IPV6_DISABLE
ipv6_gre_rewrite;
ipv6_ip_rewrite;
#ifndef NVGRE_DISABLE
ipv6_nvgre_rewrite;
#endif /* NVGRE_DISABLE */
ipv6_vxlan_rewrite;
ipv6_genv_rewrite;
#endif /* TUNNEL_OVER_IPV6_DISABLE */
#ifndef MPLS_DISABLE
mpls_ethernet_push1_rewrite;
mpls_ip_push1_rewrite;
mpls_ethernet_push2_rewrite;
mpls_ip_push2_rewrite;
mpls_ethernet_push3_rewrite;
mpls_ip_push3_rewrite;
#endif /* MPLS_DISABLE */
#endif /* TUNNEL_DISABLE */
#ifndef MIRROR_DISABLE
ipv4_erspan_t3_rewrite;
ipv6_erspan_t3_rewrite;
#endif /* MIRROR_DISABLE */
}
size : TUNNEL_HEADER_TABLE_SIZE;
}
/*****************************************************************************/
/* Tunnel rewrite */
/*****************************************************************************/
action set_tunnel_rewrite_details(outer_bd, smac_idx, dmac_idx,
sip_index, dip_index) {
modify_field(egress_metadata.outer_bd, outer_bd);
modify_field(tunnel_metadata.tunnel_smac_index, smac_idx);
modify_field(tunnel_metadata.tunnel_dmac_index, dmac_idx);
modify_field(tunnel_metadata.tunnel_src_index, sip_index);
modify_field(tunnel_metadata.tunnel_dst_index, dip_index);
}
#ifndef MPLS_DISABLE
action set_mpls_rewrite_push1(label1, exp1, ttl1, smac_idx, dmac_idx) {
modify_field(mpls[0].label, label1);
modify_field(mpls[0].exp, exp1);
modify_field(mpls[0].bos, 0x1);
modify_field(mpls[0].ttl, ttl1);
modify_field(tunnel_metadata.tunnel_smac_index, smac_idx);
modify_field(tunnel_metadata.tunnel_dmac_index, dmac_idx);
}
action set_mpls_rewrite_push2(label1, exp1, ttl1, label2, exp2, ttl2,
smac_idx, dmac_idx) {
modify_field(mpls[0].label, label1);
modify_field(mpls[0].exp, exp1);
modify_field(mpls[0].ttl, ttl1);
modify_field(mpls[0].bos, 0x0);
modify_field(mpls[1].label, label2);
modify_field(mpls[1].exp, exp2);
modify_field(mpls[1].ttl, ttl2);
modify_field(mpls[1].bos, 0x1);
modify_field(tunnel_metadata.tunnel_smac_index, smac_idx);
modify_field(tunnel_metadata.tunnel_dmac_index, dmac_idx);
}
action set_mpls_rewrite_push3(label1, exp1, ttl1, label2, exp2, ttl2,
label3, exp3, ttl3, smac_idx, dmac_idx) {
modify_field(mpls[0].label, label1);
modify_field(mpls[0].exp, exp1);
modify_field(mpls[0].ttl, ttl1);
modify_field(mpls[0].bos, 0x0);
modify_field(mpls[1].label, label2);
modify_field(mpls[1].exp, exp2);
modify_field(mpls[1].ttl, ttl2);
modify_field(mpls[1].bos, 0x0);
modify_field(mpls[2].label, label3);
modify_field(mpls[2].exp, exp3);
modify_field(mpls[2].ttl, ttl3);
modify_field(mpls[2].bos, 0x1);
modify_field(tunnel_metadata.tunnel_smac_index, smac_idx);
modify_field(tunnel_metadata.tunnel_dmac_index, dmac_idx);
}
#endif /* MPLS_DISABLE */
table tunnel_rewrite {
reads {
tunnel_metadata.tunnel_index : exact;
}
actions {
nop;
cpu_rx_rewrite;
#if !defined(TUNNEL_DISABLE) || !defined(MIRROR_DISABLE)
set_tunnel_rewrite_details;
#endif /* !TUNNEL_DISABLE || !MIRROR_DISABLE*/
#ifndef MPLS_DISABLE
set_mpls_rewrite_push1;
set_mpls_rewrite_push2;
set_mpls_rewrite_push3;
#endif /* MPLS_DISABLE */
#ifdef FABRIC_ENABLE
fabric_unicast_rewrite;
#ifndef MULTICAST_DISABLE
fabric_multicast_rewrite;
#endif /* MULTICAST_DISABLE */
#endif /* FABRIC_ENABLE */
}
size : TUNNEL_REWRITE_TABLE_SIZE;
}
#if !defined(TUNNEL_DISABLE) || !defined(MIRROR_DISABLE)
/*****************************************************************************/
/* Tunnel MTU check */
/*****************************************************************************/
action tunnel_mtu_check(l3_mtu) {
subtract(l3_metadata.l3_mtu_check, l3_mtu, egress_metadata.payload_length);
}
action tunnel_mtu_miss() {
modify_field(l3_metadata.l3_mtu_check, 0xFFFF);
}
table tunnel_mtu {
reads {
tunnel_metadata.tunnel_index : exact;
}
actions {
tunnel_mtu_check;
tunnel_mtu_miss;
}
size : TUNNEL_REWRITE_TABLE_SIZE;
}
/*****************************************************************************/
/* Tunnel source IP rewrite */
/*****************************************************************************/
action rewrite_tunnel_ipv4_src(ip) {
modify_field(ipv4.srcAddr, ip);
}
#ifndef IPV6_DISABLE
action rewrite_tunnel_ipv6_src(ip) {
modify_field(ipv6.srcAddr, ip);
}
#endif /* IPV6_DISABLE */
table tunnel_src_rewrite {
reads {
tunnel_metadata.tunnel_src_index : exact;
}
actions {
nop;
rewrite_tunnel_ipv4_src;
#ifndef IPV6_DISABLE
rewrite_tunnel_ipv6_src;
#endif /* IPV6_DISABLE */
}
size : TUNNEL_SRC_REWRITE_TABLE_SIZE;
}
/*****************************************************************************/
/* Tunnel destination IP rewrite */
/*****************************************************************************/
action rewrite_tunnel_ipv4_dst(ip) {
modify_field(ipv4.dstAddr, ip);
}
#ifndef IPV6_DISABLE
action rewrite_tunnel_ipv6_dst(ip) {
modify_field(ipv6.dstAddr, ip);
}
#endif /* IPV6_DISABLE */
table tunnel_dst_rewrite {
reads {
tunnel_metadata.tunnel_dst_index : exact;
}
actions {
nop;
rewrite_tunnel_ipv4_dst;
#ifndef IPV6_DISABLE
rewrite_tunnel_ipv6_dst;
#endif /* IPV6_DISABLE */
}
size : TUNNEL_DST_REWRITE_TABLE_SIZE;
}
action rewrite_tunnel_smac(smac) {
modify_field(ethernet.srcAddr, smac);
}
/*****************************************************************************/
/* Tunnel source MAC rewrite */
/*****************************************************************************/
table tunnel_smac_rewrite {
reads {
tunnel_metadata.tunnel_smac_index : exact;
}
actions {
nop;
rewrite_tunnel_smac;
}
size : TUNNEL_SMAC_REWRITE_TABLE_SIZE;
}
/*****************************************************************************/
/* Tunnel destination MAC rewrite */
/*****************************************************************************/
action rewrite_tunnel_dmac(dmac) {
modify_field(ethernet.dstAddr, dmac);
}
table tunnel_dmac_rewrite {
reads {
tunnel_metadata.tunnel_dmac_index : exact;
}
actions {
nop;
rewrite_tunnel_dmac;
}
size : TUNNEL_DMAC_REWRITE_TABLE_SIZE;
}
#endif /* !TUNNEL_DISABLE || !MIRROR_DISABLE*/
/*****************************************************************************/
/* Tunnel encap processing */
/*****************************************************************************/
control process_tunnel_encap {
#ifndef TUNNEL_DISABLE
if ((fabric_metadata.fabric_header_present == FALSE) and
(tunnel_metadata.egress_tunnel_type != EGRESS_TUNNEL_TYPE_NONE)) {
/* derive egress vni from egress bd */
apply(egress_vni);
/* tunnel rewrites */
if ((tunnel_metadata.egress_tunnel_type != EGRESS_TUNNEL_TYPE_FABRIC) and
(tunnel_metadata.egress_tunnel_type != EGRESS_TUNNEL_TYPE_CPU)) {
apply(tunnel_encap_process_inner);
}
apply(tunnel_encap_process_outer);
apply(tunnel_rewrite);
apply(tunnel_mtu);
/* rewrite tunnel src and dst ip */
apply(tunnel_src_rewrite);
apply(tunnel_dst_rewrite);
/* rewrite tunnel src and dst ip */
apply(tunnel_smac_rewrite);
apply(tunnel_dmac_rewrite);
}
#endif /* TUNNEL_DISABLE */
}
2016/11/26
tunnel.p4的更多相关文章
- 外网访问内网工具ngrok tunnel 使用总结
需求分析 在软件开发测试过程中,我们会经常遇到需要网站部署测试.给客户演示.APP开发的调试这样的需求.通常的做法是申请一个域名和空间,将网站放到外网上给客户演示. 这种方法确实可行不过会有两点不好, ...
- ssh reverse tunnel
ssh反向通道的可用场景之一:从外网访问内网的主机.所必须的是你需要一个有ssh登录权限的公网主机. 步骤如下(将内网主机称作A,公网ssh主机地址为hostP ): 1.在内网A上执行 :local ...
- Run P4 without P4factory - A Simple Example In Tutorials.
前言 本文是我运行P4社区于Github开源教程Tutorials中的P4 SIGCOMM 2015 Tutorial一些实战小结,Github链接: Github. 测试的例子:P4 SIGCOMM ...
- Sublime P4语法高亮设置
Github插件链接:p4-syntax-highlighter 首先安装Package Control. 进入Package界面,我的目录: /Users/wasdns/Library/Applic ...
- hdu1540 Tunnel Warfare
Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- P4基函数
July , P4 syms p1 p2 p3 phi(:,) = /*p1.*(*p1-).*(*p1-).*(*p1-); phi(:,) = /*p2.*(*p2-).*(*p2-).*(*p2 ...
- 通过ssh tunnel连接内网ECS和RDS
通过ssh tunnel连接内网ECS和RDS 这里讲了ssh tunnel的原理.很清晰. 此后又给外网访问内网增加了一种思路.感觉特别棒. 拓宽了思路:
- 【动态域名解析工具】tunnel,国内版的ngrok,花生壳可以睡觉了
在笔者的系列微信开发教程中,有一个比较基础且重要的一节:微信开发的调试.在文章中我推荐了两种动态域名解析的工具用于将本地的开发环境部署成服务器,一种是花生壳,一种是ngrok,但毕竟我等屌丝用不起或者 ...
- [POJ2892]Tunnel Warfare
[POJ2892]Tunnel Warfare 试题描述 During the War of Resistance Against Japan, tunnel warfare was carried ...
随机推荐
- java基础知识回顾之javaIO类总结
java IO体系图 IO流的操作规律总结: 1,明确体系: 数据源:InputStream ,Reader 数据汇:OutputStream,Writer 2,明确数据:因为数据分两种:字节,字符. ...
- UML中的关联关系
UML中的关联关系其内在意思就是has a 如图: 相对于依赖关系,关联关系在代码中有所体现.上图中的关联关系在代码中体现为 其中water 中将Climate作为其中的属性. 当然,关 ...
- oracle的关闭过程(各个模式关闭)
关闭数据库与实例 与数据库启动一下,关闭数据库与实例也分为3步:关闭数据库-->实例卸载数据库--->终止实例. 1.Nomal(正常关闭方式) 命令:shutdown nomal 讲解: ...
- BC#32 1002 hash
代码引用kuangbin大神的,膜拜 第一次见到hashmap和外挂,看来还有很多东西要学 维护前缀和sum[i]=a[0]-a[1]+a[2]-a[3]+…+(-1)^i*a[i] 枚举结尾i,然后 ...
- 【现代程序设计】homework-06
1) 把程序编译通过, 跑起来. 读懂程序,在你觉得比较难懂的地方加上一些注释,这样大家就能比较容易地了解这些程序在干什么. 把正确的 playPrev(GoMove) 的方法给实现了. 如果大家不会 ...
- CC2540开发板学习笔记(九)—— BLE协议简介
一.BLE协议简介 1.协议是什么? 协议是一系列的通信标准,双方需要共同按照这进行正常数据 协议是一系列的通信标准,双方需要共同按照这进行正常数据发射和 接收.协议栈是的具体实现形式,通俗点来理解就 ...
- Kinect学习笔记(五)——更专业的深度图
这一节的内容就是把深度图转换为彩色图,然后不再使用硬解码,而是继续采用sdk里面封装好的功能来减少测量的误差,以及避免转换为灰度图时,出现绿巨人时候的掉针的bug. 下面直接 ...
- ITEYE中的读书笔记:重构其实就是持续改进
原文地址:http://hawkon.iteye.com/blog/2093338#bc2355877 前段时间同事参加ITEYE的试读有奖, 没想到得了个奖,拿到一本书.由于同事的推荐我也认真读了一 ...
- 关于adb驱动
Android设备(如手机)连接PC时所需要的驱动程序,一般Android设备连接WinXP是无需安装驱动的. adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb ...
- apple个人开发者证书无线发布app的实现(转)
解释一下这标题:apple个人开发者证书无线发布app的实现,也就是说不经过发布到app store,直接在ios设备上安装app,注:ios设备不需要越狱. 之所以有这篇文章的产生,可以看这里: 不 ...