2 changed files with 375 additions and 0 deletions
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python |
||||
|
||||
# |
||||
# Copyright (c) 2015 University of Cambridge |
||||
# All rights reserved. |
||||
# |
||||
# This software was developed by Stanford University and the University of Cambridge Computer Laboratory |
||||
# under National Science Foundation under Grant No. CNS-0855268, |
||||
# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and |
||||
# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), |
||||
# as part of the DARPA MRC research programme. |
||||
# |
||||
# @NETFPGA_LICENSE_HEADER_START@ |
||||
# |
||||
# Licensed to NetFPGA C.I.C. (NetFPGA) under one or more contributor |
||||
# license agreements. See the NOTICE file distributed with this work for |
||||
# additional information regarding copyright ownership. NetFPGA licenses this |
||||
# file to you under the NetFPGA Hardware-Software License, Version 1.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.netfpga-cic.org |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, Work 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. |
||||
# |
||||
# @NETFPGA_LICENSE_HEADER_END@ |
||||
# |
||||
|
||||
from NFTest import * |
||||
import sys, os, re, json |
||||
from fcntl import * |
||||
from ctypes import * |
||||
from collections import OrderedDict |
||||
|
||||
# Loading the SUME shared library |
||||
print "loading libsume.." |
||||
lib_path=os.path.join(os.environ['SUME_FOLDER'],'lib','sw','std','hwtestlib','libsume.so') |
||||
libsume=cdll.LoadLibrary(lib_path) |
||||
|
||||
# argtypes for the functions called from C |
||||
libsume.regread.argtypes = [c_uint] |
||||
libsume.regwrite.argtypes= [c_uint, c_uint] |
||||
|
||||
EXTERN_DEFINES_FILE = os.path.expandvars("$P4_PROJECT_DIR/sw/CLI/SimpleSumeSwitch_extern_defines.json") |
||||
|
||||
ERROR_CODE = -1 |
||||
|
||||
""" |
||||
Read the SimpleSumeSwitch_reg_defines.txt file |
||||
""" |
||||
def read_extern_defines(): |
||||
with open(EXTERN_DEFINES_FILE) as f: |
||||
p4_externs = json.load(f) |
||||
return p4_externs |
||||
|
||||
def get_address(reg_name, index): |
||||
global PX_EXTERNS |
||||
if reg_name not in P4_EXTERNS.keys() and 'control_width' not in P4_EXTERNS[reg_name].keys() and P4_EXTERNS[reg_name]['control_width'] > 0: |
||||
print >> sys.stderr, "ERROR: {0} is not a recognized register name".format(reg_name) |
||||
return ERROR_CODE |
||||
addressable_depth = 2**P4_EXTERNS[reg_name]['control_width'] |
||||
if index >= addressable_depth or index < 0: |
||||
print >> sys.stderr, "ERROR: cannot access {0}[{1}], index out of bounds".format(reg_name, index) |
||||
return ERROR_CODE |
||||
return P4_EXTERNS[reg_name]['base_addr'] + index |
||||
|
||||
# P4_EXTERNS is indexed by prefix_name |
||||
P4_EXTERNS = read_extern_defines() |
||||
|
||||
##################### |
||||
### API Functions ### |
||||
##################### |
||||
|
||||
def reg_read(reg_name, index): |
||||
address = get_address(reg_name, index) |
||||
if address == ERROR_CODE: |
||||
return ERROR_CODE |
||||
# print "reading address : {0}".format(hex(address)) |
||||
return libsume.regread(address) |
||||
|
||||
def reg_write(reg_name, index, val): |
||||
address = get_address(reg_name, index) |
||||
if address == ERROR_CODE: |
||||
return ERROR_CODE |
||||
# print "writing address : {0}".format(hex(address)) |
||||
return libsume.regwrite(address, val) |
||||
|
@ -0,0 +1,285 @@
|
||||
#!/usr/bin/env python |
||||
|
||||
# |
||||
# Copyright (c) 2017 Stephen Ibanez |
||||
# All rights reserved. |
||||
# |
||||
# This software was developed by Stanford University and the University of Cambridge Computer Laboratory |
||||
# under National Science Foundation under Grant No. CNS-0855268, |
||||
# the University of Cambridge Computer Laboratory under EPSRC INTERNET Project EP/H040536/1 and |
||||
# by the University of Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249 ("MRC2"), |
||||
# as part of the DARPA MRC research programme. |
||||
# |
||||
# @NETFPGA_LICENSE_HEADER_START@ |
||||
# |
||||
# Licensed to NetFPGA C.I.C. (NetFPGA) under one or more contributor |
||||
# license agreements. See the NOTICE file distributed with this work for |
||||
# additional information regarding copyright ownership. NetFPGA licenses this |
||||
# file to you under the NetFPGA Hardware-Software License, Version 1.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.netfpga-cic.org |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, Work 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. |
||||
# |
||||
# @NETFPGA_LICENSE_HEADER_END@ |
||||
# |
||||
|
||||
from NFTest import * |
||||
import sys, os, re, json |
||||
from fcntl import * |
||||
from ctypes import * |
||||
|
||||
SWITCH_INFO_FILE = os.path.expandvars("$P4_PROJECT_DIR/src/.sdnet_switch_info.dat") |
||||
|
||||
# sets PX_TABLES |
||||
import p4_px_tables |
||||
p4_px_tables.make_px_tables(SWITCH_INFO_FILE) |
||||
|
||||
PX_CAM_TABLES = {} |
||||
PX_TCAM_TABLES = {} |
||||
PX_LPM_TABLES = {} |
||||
|
||||
def split_px_tables(): |
||||
for name, table in p4_px_tables.PX_TABLES.items(): |
||||
if table.info['match_type'] == 'EM': |
||||
PX_CAM_TABLES[name] = table |
||||
elif table.info['match_type'] == 'TCAM': |
||||
PX_TCAM_TABLES[name] = table |
||||
elif table.info['match_type'] == 'LPM': |
||||
PX_LPM_TABLES[name] = table |
||||
|
||||
split_px_tables() |
||||
|
||||
if (len(PX_CAM_TABLES) > 0): |
||||
print "loading libcam.." |
||||
libcam=cdll.LoadLibrary(os.path.expandvars('$P4_PROJECT_DIR/sw/CLI/libcam.so')) |
||||
|
||||
# argtypes for the functions called from C |
||||
libcam.cam_read_entry.argtypes = [c_uint, c_char_p, c_char_p, c_char_p] |
||||
libcam.cam_add_entry.argtypes = [c_uint, c_char_p, c_char_p] |
||||
libcam.cam_delete_entry.argtypes = [c_uint, c_char_p] |
||||
libcam.cam_error_decode.argtypes = [c_int] |
||||
libcam.cam_error_decode.restype = c_char_p |
||||
libcam.cam_get_size.argtypes = [c_uint] |
||||
libcam.cam_get_size.restype = c_uint |
||||
|
||||
if (len(PX_TCAM_TABLES) > 0): |
||||
print "loading libtcam.." |
||||
libtcam=cdll.LoadLibrary(os.path.expandvars('$P4_PROJECT_DIR/sw/CLI/libtcam.so')) |
||||
|
||||
# argtypes for the functions called from C |
||||
libtcam.tcam_clean.argtypes = [c_uint] |
||||
libtcam.tcam_get_addr_size.argtypes = [] |
||||
libtcam.tcam_set_log_level.argtypes = [c_uint, c_uint] |
||||
libtcam.tcam_write_entry.argtypes = [c_uint, c_uint, c_char_p, c_char_p, c_char_p] |
||||
libtcam.tcam_erase_entry.argtypes = [c_uint, c_uint] |
||||
libtcam.tcam_verify_entry.argtypes = [c_uint, c_uint, c_char_p, c_char_p, c_char_p] |
||||
libtcam.tcam_verify_entry.restype = c_uint |
||||
libtcam.tcam_error_decode.argtypes = [c_int] |
||||
libtcam.tcam_error_decode.restype = c_char_p |
||||
|
||||
if (len(PX_LPM_TABLES) > 0): |
||||
print "loading liblpm.." |
||||
liblpm=cdll.LoadLibrary(os.path.expandvars('$P4_PROJECT_DIR/sw/CLI/liblpm.so')) |
||||
|
||||
# argtypes for the functions called from C |
||||
liblpm.lpm_get_addr_size.argtypes = [] |
||||
liblpm.lpm_set_log_level.argtypes = [c_uint, c_uint] |
||||
liblpm.lpm_load_dataset.argtypes = [c_uint, c_char_p] |
||||
liblpm.lpm_verify_dataset.argtypes = [c_uint, c_char_p] |
||||
liblpm.lpm_set_active_lookup_bank.argtypes = [c_uint, c_uint] |
||||
liblpm.lpm_error_decode.argtypes = [c_int] |
||||
liblpm.lpm_error_decode.restype = c_char_p |
||||
|
||||
TABLE_DEFINES_FILE = os.path.expandvars("$P4_PROJECT_DIR/sw/CLI/SimpleSumeSwitch_table_defines.json") |
||||
|
||||
######################## |
||||
### Helper Functions ### |
||||
######################## |
||||
|
||||
""" |
||||
def the SimpleSumeSwitch_table_defines.json file |
||||
""" |
||||
def read_table_defines(): |
||||
with open(TABLE_DEFINES_FILE) as f: |
||||
tables_dict = json.load(f) |
||||
return tables_dict |
||||
|
||||
|
||||
p4_tables_info = read_table_defines() |
||||
|
||||
""" |
||||
Check if table_name is a valid CAM table |
||||
""" |
||||
def check_valid_cam_table_name(table_name): |
||||
if (table_name not in PX_CAM_TABLES.keys() and table_name not in p4_tables_info['EM'].keys()): |
||||
print >> sys.stderr, "ERROR: {0} is not a recognized CAM table name".format(table_name) |
||||
return False |
||||
return True |
||||
|
||||
""" |
||||
Check if table_name is a valid TCAM table |
||||
""" |
||||
def check_valid_tcam_table_name(table_name): |
||||
if (table_name not in PX_TCAM_TABLES.keys() and table_name not in p4_tables_info['TCAM'].keys()): |
||||
print >> sys.stderr, "ERROR: {0} is not a recognized TCAM table name".format(table_name) |
||||
return False |
||||
return True |
||||
|
||||
""" |
||||
Check if table_name is a valid LPM table |
||||
""" |
||||
def check_valid_lpm_table_name(table_name): |
||||
if (table_name not in PX_LPM_TABLES.keys() and table_name not in p4_tables_info['LPM'].keys()): |
||||
print >> sys.stderr, "ERROR: {0} is not a recognized LPM table name".format(table_name) |
||||
return False |
||||
return True |
||||
|
||||
######################### |
||||
### CAM API Functions ### |
||||
######################### |
||||
|
||||
def table_cam_read_entry(table_name, keys): |
||||
if not check_valid_cam_table_name(table_name): |
||||
return "NA", "NA" |
||||
|
||||
tableID = int(p4_tables_info['EM'][table_name]['tableID']) |
||||
key = PX_CAM_TABLES[table_name].hexify_key(keys) |
||||
hex_key_buf = create_string_buffer("{:X}".format(key)) |
||||
value = create_string_buffer(1024) # TODO: Fix this ... Must be large enough to hold entire value |
||||
found = create_string_buffer(10) # Should only need to hold "True" or "False" |
||||
rc = libcam.cam_read_entry(tableID, hex_key_buf, value, found) |
||||
print libcam.cam_error_decode(rc) |
||||
return found.value, value.value |
||||
|
||||
def table_cam_add_entry(table_name, keys, action_name, action_data): |
||||
if not check_valid_cam_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['EM'][table_name]['tableID']) |
||||
key = PX_CAM_TABLES[table_name].hexify_key(keys) |
||||
value = PX_CAM_TABLES[table_name].hexify_value(action_name, action_data) |
||||
rc = libcam.cam_add_entry(tableID, "{:X}".format(key), "{:X}".format(value)) |
||||
print libcam.cam_error_decode(rc) |
||||
|
||||
def table_cam_delete_entry(table_name, keys): |
||||
if not check_valid_cam_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['EM'][table_name]['tableID']) |
||||
key = PX_CAM_TABLES[table_name].hexify_key(keys) |
||||
rc = libcam.cam_delete_entry(tableID, "{:X}".format(key)) |
||||
print libcam.cam_error_decode(rc) |
||||
|
||||
def table_cam_get_size(table_name): |
||||
if not check_valid_cam_table_name(table_name): |
||||
return 0 |
||||
|
||||
tableID = int(p4_tables_info['EM'][table_name]['tableID']) |
||||
return libcam.cam_get_size(tableID) |
||||
|
||||
|
||||
########################## |
||||
### TCAM API Functions ### |
||||
########################## |
||||
|
||||
def table_tcam_clean(table_name): |
||||
if not check_valid_tcam_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['TCAM'][table_name]['tableID']) |
||||
rc = libtcam.tcam_clean(tableID) |
||||
print libtcam.tcam_error_decode(rc) |
||||
|
||||
def table_tcam_get_addr_size(): |
||||
return libtcam.tcam_get_addr_size() |
||||
|
||||
def table_tcam_set_log_level(table_name, msg_level): |
||||
if not check_valid_tcam_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['TCAM'][table_name]['tableID']) |
||||
rc = libtcam.tcam_set_log_level(tableID, msg_level) |
||||
print libtcam.tcam_error_decode(rc) |
||||
|
||||
def table_tcam_write_entry(table_name, addr, keys, masks, action_name, action_data): |
||||
if not check_valid_tcam_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['TCAM'][table_name]['tableID']) |
||||
mask = PX_TCAM_TABLES[table_name].hexify_mask(masks) |
||||
key = PX_TCAM_TABLES[table_name].hexify_key(keys) |
||||
value = PX_TCAM_TABLES[table_name].hexify_value(action_name, action_data) |
||||
rc = libtcam.tcam_write_entry(tableID, addr, "{:X}".format(key), "{:X}".format(mask), "{:X}".format(value)) |
||||
print libtcam.tcam_error_decode(rc) |
||||
|
||||
def table_tcam_erase_entry(table_name, addr): |
||||
if not check_valid_tcam_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['TCAM'][table_name]['tableID']) |
||||
rc = libtcam.tcam_erase_entry(tableID, addr) |
||||
print libtcam.tcam_error_decode(rc) |
||||
|
||||
|
||||
def table_tcam_verify_entry(table_name, addr, keys, masks, action_name, action_data): |
||||
if not check_valid_tcam_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['TCAM'][table_name]['tableID']) |
||||
mask = PX_TCAM_TABLES[table_name].hexify_mask(masks) |
||||
key = PX_TCAM_TABLES[table_name].hexify_key(keys) |
||||
value = PX_TCAM_TABLES[table_name].hexify_value(action_name, action_data) |
||||
return libtcam.tcam_verify_entry(tableID, addr, "{:X}".format(key), "{:X}".format(mask), "{:X}".format(value)) |
||||
|
||||
def table_tcam_error_decode(error): |
||||
return libtcam.tcam_error_decode(error) |
||||
|
||||
|
||||
######################### |
||||
### LPM API Functions ### |
||||
######################### |
||||
|
||||
def table_lpm_get_addr_size(): |
||||
return liblpm.lpm_get_addr_size() |
||||
|
||||
def table_lpm_set_log_level(table_name): |
||||
if not check_valid_lpm_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['LPM'][table_name]['tableID']) |
||||
rc = liblpm.lpm_set_log_level(tableID, msg_level) |
||||
print liblpm.lpm_error_decode(rc) |
||||
|
||||
def table_lpm_load_dataset(table_name, filename): |
||||
if not check_valid_lpm_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['LPM'][table_name]['tableID']) |
||||
rc = liblpm.lpm_load_dataset(tableID, filename) |
||||
print liblpm.lpm_error_decode(rc) |
||||
|
||||
def table_lpm_verify_dataset(table_name, filename): |
||||
if not check_valid_lpm_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['LPM'][table_name]['tableID']) |
||||
return liblpm.lpm_verify_dataset(tableID, filename) |
||||
|
||||
def table_lpm_set_active_lookup_bank(table_name, bank): |
||||
if not check_valid_lpm_table_name(table_name): |
||||
return |
||||
|
||||
tableID = int(p4_tables_info['LPM'][table_name]['tableID']) |
||||
rc = liblpm.lpm_set_active_lookup_bank(tableID, bank) |
||||
print liblpm.lpm_error_decode(rc) |
||||
|
||||
def table_lpm_error_decode(error): |
||||
return liblpm.lpm_error_decode(error) |
||||
|
||||
|
Loading…
Reference in new issue