blob: dcabea730907438de30bd4a18e56844a978bdf43 [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.
*/
#include <core.p4>
#include <v1model.p4>
#include "../header.p4"
#include "../action.p4"
control Filtering (
inout parsed_headers_t hdr,
inout fabric_metadata_t fabric_metadata,
inout standard_metadata_t standard_metadata) {
/*
* Ingress Port VLAN Table.
* Process packets for different interfaces (Port number + VLAN).
* For example, an untagged packet will be tagged when it entered to an
* interface with untagged VLAN configuration.
*/
direct_counter(CounterType.packets_and_bytes) ingress_port_vlan_counter;
action drop() {
mark_to_drop();
ingress_port_vlan_counter.count();
}
action set_vlan(vlan_id_t new_vlan_id) {
hdr.vlan_tag.vlan_id = new_vlan_id;
ingress_port_vlan_counter.count();
}
action push_internal_vlan(vlan_id_t new_vlan_id) {
// Add internal VLAN header, will be removed before packet emission.
// cfi and pri values are dummy.
hdr.vlan_tag.setValid();
hdr.vlan_tag.cfi = 0;
hdr.vlan_tag.pri = 0;
hdr.vlan_tag.ether_type = hdr.ethernet.ether_type;
hdr.ethernet.ether_type = ETHERTYPE_VLAN;
hdr.vlan_tag.vlan_id = new_vlan_id;
// pop internal vlan before packet in
fabric_metadata.pop_vlan_when_packet_in = _TRUE;
ingress_port_vlan_counter.count();
}
action nop_ingress_port_vlan() {
nop();
ingress_port_vlan_counter.count();
}
table ingress_port_vlan {
key = {
standard_metadata.ingress_port: exact;
hdr.vlan_tag.isValid(): exact @name("hdr.vlan_tag.is_valid");
hdr.vlan_tag.vlan_id: ternary;
}
actions = {
push_internal_vlan;
set_vlan;
drop;
nop_ingress_port_vlan();
}
const default_action = push_internal_vlan(DEFAULT_VLAN_ID);
counters = ingress_port_vlan_counter;
}
/*
* Forwarding Classifier.
* Setup Forwarding Type metadata for Forwarding control block.
* There are six types of tables in Forwarding control block:
* - Bridging: default forwarding type
* - MPLS: destination mac address is the router mac and ethernet type is
* MPLS(0x8847)
* - IP Multicast: destination mac address is multicast address and ethernet
* type is IP(0x0800 or 0x86dd)
* - IP Unicast: destination mac address is router mac and ethernet type is
* IP(0x0800 or 0x86dd)
*/
direct_counter(CounterType.packets_and_bytes) fwd_classifier_counter;
action set_forwarding_type(fwd_type_t fwd_type) {
fabric_metadata.fwd_type = fwd_type;
fwd_classifier_counter.count();
}
table fwd_classifier {
key = {
standard_metadata.ingress_port: exact;
hdr.ethernet.dst_addr: exact;
hdr.vlan_tag.ether_type: exact;
}
actions = {
set_forwarding_type;
}
const default_action = set_forwarding_type(FWD_BRIDGING);
counters = fwd_classifier_counter;
}
apply {
if (ingress_port_vlan.apply().hit) {
fwd_classifier.apply();
} else {
// Packet from unconfigured port. Skip forwarding processing,
// except for ACL table in case we want to punt to cpu.
fabric_metadata.fwd_type = FWD_UNKNOWN;
}
}
}