/* * Copyright 2020-present Ralf Kundel * * 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. */ #define SOJOURN_TARGET 5000000 //in nsec #define CONTROL_INTERVAL 100000000 //in nsec typedef bit<32> data_t; typedef bit<1> box_num_t; struct register_operations { bit<32> val1; bit<32> val2; } struct codel_metadata_t{ bit<32> egress_tstamp; bit<32> queue_delay; bit<32> sojourn_remainder; bit<1> sojourn_violation; bit<1> first_sojourn_violation; bit<1> codel_drop; bit<32> drop_counter_result; bit<8> temp_flag; bit<16> temp_tstamp_high; bit<32> temp_tstamp_low; } control CoDelEgress (in bit<48> ingress_tstamp, in bit<48> egress_tstamp, in bit<9> egress_port, inout headers_t hdr, inout egress_intrinsic_metadata_for_deparser_t eg_intr_md_for_dprsr){ codel_metadata_t codel_metadata; //Drop Counter Register(32w1) drop_counter; RegisterAction(drop_counter) update_counter = { void apply(inout data_t counter_data, out data_t counter_result){ counter_result = counter_data; counter_data = counter_result + 1; } }; //Stateful ALU1 Register< bit<32>, bit<9> > (32w512) codel_drop_state; RegisterAction, bit<9>, bit<1> >(codel_drop_state) codel_drop_state_action = { void apply(inout bit<32> drop_state, out bit<1> first_soujourn_violation){ if(drop_state== 32w0x0 && codel_metadata.sojourn_violation == 1w0x1){ first_soujourn_violation = 1w0x1; }else{ first_soujourn_violation = 1w0x0; } if(codel_metadata.sojourn_violation == 1w0x1){ drop_state = 32w0x1; }else { drop_state = 32w0x0; } } }; //Stateful ALU2 MathUnit< bit<32> > (true, -1, 20, {0x46, 0x48, 0x4b, 0x4e, 0x52, 0x56, 0x5a, 0x60, 0x66, 0x6f, 0x79, 0x87, 0x0, 0x0, 0x0, 0x0}) sqrtn; Register< register_operations, bit<9>> (32w512) codel_salu_2; RegisterAction, bit<1> >(codel_salu_2) codel_salu_2_action = { void apply(inout register_operations inout_vals, out bit<1> out_val){ //val2 == drop count //val1 == next_drop_time out_val = 1w0x0; if(codel_metadata.first_sojourn_violation == 1w0x1){ inout_vals.val1 = codel_metadata.egress_tstamp + CONTROL_INTERVAL; inout_vals.val2 = 1; } else if(codel_metadata.egress_tstamp > inout_vals.val1) { //we want to drop inout_vals.val2 = inout_vals.val2 + 1; inout_vals.val1 = inout_vals.val1 + sqrtn.execute(inout_vals.val2); out_val = 1w0x1; } } }; action a_compute_remainder(){ codel_metadata.sojourn_remainder = SOJOURN_TARGET |-| codel_metadata.queue_delay; } table t_compute_remainder { actions = { a_compute_remainder; } default_action = a_compute_remainder; } action a_drop(){ eg_intr_md_for_dprsr.drop_ctl = 3w0x1; } apply{ codel_metadata.temp_flag = 8w0x0; //codel_metadata.drop_counter_result=update_counter.execute((bit<1>)0); eg_intr_md_for_dprsr.drop_ctl = 3w0x0; //default value, otherwise the value is undefined in case of "non dropping" and everything can happen codel_metadata.egress_tstamp = (bit<32>) egress_tstamp; codel_metadata.queue_delay = (bit<32>)(egress_tstamp - ingress_tstamp); t_compute_remainder.apply(); if(codel_metadata.sojourn_remainder == 0){ codel_metadata.sojourn_violation = 1w0x1; }else{ codel_metadata.sojourn_violation = 1w0x0; } codel_metadata.first_sojourn_violation = codel_drop_state_action.execute(egress_port); codel_metadata.codel_drop = codel_salu_2_action.execute(egress_port); if( (codel_metadata.codel_drop == 1w0x1) && (codel_metadata.sojourn_violation == 1w0x1) ){ a_drop(); codel_metadata.drop_counter_result=update_counter.execute((bit<1>)0); //codel_metadata.temp_flag = 8w0x1; //write_drop_flag_state.execute(egress_port); //codel_metadata.temp_tstamp_high = egress_tstamp[47:32]; //write_drop_tstamp_high.execute(egress_port); //codel_metadata.temp_tstamp_low = egress_tstamp[31:0]; //write_drop_tstamp_low.execute(egress_port); // //update_counter.execute((bit<1>)0); // update counter } else { //codel_metadata.temp_flag = read_drop_flag_state.execute(egress_port); //if (codel_metadata.temp_flag == 1) { /* hdr.my_tstamp.drop_flag = 1; hdr.my_tstamp.drop_tstamp_high = read_drop_tstamp_high.execute(egress_port); hdr.my_tstamp.drop_tstamp_low = read_drop_tstamp_low.execute(egress_port); } else { hdr.my_tstamp.drop_flag =0; }*/ } } }