lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1482310011-1862-7-git-send-email-satha.rao@caviumnetworks.com>
Date:   Wed, 21 Dec 2016 14:16:50 +0530
From:   Satha Koteswara Rao <satha.rao@...iumnetworks.com>
To:     <linux-kernel@...r.kernel.org>
CC:     <sgoutham@...ium.com>, <rric@...nel.org>, <davem@...emloft.net>,
        <david.daney@...ium.com>, <rvatsavayi@...iumnetworks.com>,
        <derek.chickles@...iumnetworks.com>,
        <satha.rao@...iumnetworks.com>, <philip.romanov@...ium.com>,
        <netdev@...r.kernel.org>, <linux-arm-kernel@...ts.infradead.org>
Subject: [RFC PATCH 6/7] HW Filter Table access API's

---
 drivers/net/ethernet/cavium/thunder/tbl_access.c | 262 +++++++++++++++++++++++
 drivers/net/ethernet/cavium/thunder/tbl_access.h |  61 ++++++
 2 files changed, 323 insertions(+)
 create mode 100644 drivers/net/ethernet/cavium/thunder/tbl_access.c
 create mode 100644 drivers/net/ethernet/cavium/thunder/tbl_access.h

diff --git a/drivers/net/ethernet/cavium/thunder/tbl_access.c b/drivers/net/ethernet/cavium/thunder/tbl_access.c
new file mode 100644
index 0000000..6be31eb
--- /dev/null
+++ b/drivers/net/ethernet/cavium/thunder/tbl_access.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2015 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/uaccess.h>
+#include "pf_globals.h"
+#include "pf_locals.h"
+#include "tbl_access.h"
+
+struct tns_table_s *get_table_information(int table_id)
+{
+	int i;
+
+	for (i = 0; i < TNS_MAX_TABLE; i++) {
+		if (!tbl_info[i].sdata.valid)
+			continue;
+
+		if (tbl_info[i].sdata.tbl_id == table_id)
+			return &tbl_info[i];
+	}
+
+	return NULL;
+}
+
+int tbl_write(int node, int table_id, int tbl_index, void *key, void *mask,
+	      void *data)
+{
+	int i;
+	struct tns_table_s *tbl = get_table_information(table_id);
+	int bck_cnt, data_index, data_offset;
+	u64 data_entry[4];
+
+	if (!tbl) {
+		filter_dbg(FERR, "Invalid Table ID: %d\n", table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	bck_cnt = tbl->sdata.data_width / tbl->sdata.data_size;
+	data_index = (tbl_index / bck_cnt);
+	data_offset = (tbl_index % bck_cnt);
+	//TCAM Table, we need to parse key & mask into single array
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		struct filter_keymask_s *tk = (struct filter_keymask_s *)key;
+		struct filter_keymask_s *tm = (struct filter_keymask_s *)mask;
+		u8 km[32];
+		u64 mod_key, mod_mask, temp_mask;
+		int index = 0, offset = 0;
+
+		memset(km, 0x0, 32);
+
+/* TCAM truth table data creation. Translation from data/mask to following
+ * truth table:
+ *
+ *         Mask   Data     Content
+ *          0     0         X
+ *          0     1         1
+ *          1     0         0
+ *          1     1         Always Mismatch
+ *
+ */
+		mod_mask = ~tk->key_value;
+		temp_mask = tm->key_value;
+		mod_key = tk->key_value;
+		mod_key = mod_key & (~temp_mask);
+		mod_mask = mod_mask & (~temp_mask);
+
+		for (i = 0; i < 64; i++) {
+			km[index] = km[index] | (((mod_mask >> i) & 0x1) <<
+						 offset);
+			km[index] = km[index] | (((mod_key >> i) & 0x1) <<
+						 (offset + 1));
+			offset += 2;
+			if (offset == 8) {
+				offset = 0;
+				index += 1;
+			}
+		}
+		km[index] = 0x2;
+		if (tns_write_register_indirect(node,
+						(tbl->sdata.key_base_addr +
+						 (tbl_index * 32)), 32,
+						(void *)&km[0])) {
+			filter_dbg(FERR, "key write failed node %d tbl ID %d",
+				   node, table_id);
+			filter_dbg(FERR, " index %d\n", tbl_index);
+			return TNS_ERR_DRIVER_WRITE;
+		}
+	}
+
+	/* Data Writes are ReadModifyWrite */
+	if (tns_read_register_indirect(node, (tbl->sdata.data_base_addr +
+					      (data_index * 32)), 32,
+				       (void *)&data_entry[0])) {
+		filter_dbg(FERR, "data read failed node %d tbl ID %d idx %d\n",
+			   node, table_id, tbl_index);
+		return TNS_ERR_DRIVER_READ;
+	}
+	memcpy(&data_entry[data_offset], data, tbl->sdata.data_size / 8);
+	if (tns_write_register_indirect(node, (tbl->sdata.data_base_addr +
+					       (data_index * 32)), 32,
+					(void *)&data_entry[0])) {
+		filter_dbg(FERR, "data write failed node %d tbl ID %d idx %d\n",
+			   node, table_id, tbl_index);
+		return TNS_ERR_DRIVER_WRITE;
+	}
+
+	return TNS_NO_ERR;
+}
+
+int tbl_read(int node, int table_id, int tbl_index, void *key, void *mask,
+	     void *data)
+{
+	struct tns_table_s *tbl = get_table_information(table_id);
+	int i, bck_cnt, data_index, data_offset;
+	u64 data_entry[4];
+	u8 km[32];
+
+	if (!tbl) {
+		filter_dbg(FERR, "Invalid Table ID: %d\n", table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	bck_cnt = tbl->sdata.data_width / tbl->sdata.data_size;
+	data_index = (tbl_index / bck_cnt);
+	data_offset = (tbl_index % bck_cnt);
+
+	//TCAM Table, we need to parse key & mask into single array
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		memset(km, 0x0, 32);
+
+		if (tns_read_register_indirect(node, (tbl->sdata.key_base_addr +
+						      (tbl_index * 32)), 32,
+					       (void *)&km[0])) {
+			filter_dbg(FERR, "key read failed node %d tbl ID %d",
+				   node, table_id);
+			filter_dbg(FERR, " idx %d\n", tbl_index);
+			return TNS_ERR_DRIVER_READ;
+		}
+		if (!(km[((tbl->sdata.key_size * 2) / 8)] == 0x2))
+			return TNS_ERR_MAC_FILTER_INVALID_ENTRY;
+	}
+
+	if (tns_read_register_indirect(node, (tbl->sdata.data_base_addr +
+					      (data_index * 32)), 32,
+				       (void *)&data_entry[0])) {
+		filter_dbg(FERR, "data read failed node %d tbl ID %d idx %d\n",
+			   node, table_id, tbl_index);
+		return TNS_ERR_DRIVER_READ;
+	}
+	memcpy(data, (void *)(&data_entry[data_offset]),
+	       (tbl->sdata.data_size / 8));
+
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		struct filter_keymask_s *tk = (struct filter_keymask_s *)key;
+		struct filter_keymask_s *tm = (struct filter_keymask_s *)mask;
+		u8 temp_km;
+		int index = 0, offset = 0;
+
+		tk->key_value = 0x0ull;
+		tm->key_value = 0x0ull;
+		temp_km = km[0];
+		for (i = 0; i < 64; i++) {
+			tm->key_value = tm->key_value |
+					 ((temp_km & 0x1ull) << i);
+			temp_km >>= 1;
+			tk->key_value = tk->key_value |
+					 ((temp_km & 0x1ull) << i);
+			temp_km >>= 1;
+			offset += 2;
+			if (offset == 8) {
+				offset = 0;
+				index += 1;
+				temp_km = km[index];
+			}
+		}
+		tm->key_value = ~tm->key_value & ~tk->key_value;
+		tk->is_valid = 1;
+		tm->is_valid = 0;
+	}
+
+	return TNS_NO_ERR;
+}
+
+int invalidate_table_entry(int node, int table_id, int tbl_idx)
+{
+	struct tns_table_s *tbl = get_table_information(table_id);
+
+	if (!tbl) {
+		filter_dbg(FERR, "Invalid Table ID: %d\n", table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	if (tbl->sdata.tbl_type == TNS_TBL_TYPE_TT) {
+		u8 km[32];
+
+		memset(km, 0x0, 32);
+		km[((tbl->sdata.key_size * 2) / 8)] = 0x1;
+
+		if (tns_write_register_indirect(node,
+						(tbl->sdata.key_base_addr +
+						 (tbl_idx * 32)), 32,
+						(void *)&km[0])) {
+			filter_dbg(FERR, "%s failed node %d tbl ID %d idx %d\n",
+				   __func__, node, table_id, tbl_idx);
+			return TNS_ERR_DRIVER_WRITE;
+		}
+	}
+
+	return TNS_NO_ERR;
+}
+
+int alloc_table_index(int node, int table_id, int *index)
+{
+	int err = 0;
+	struct tns_table_s *tbl = get_table_information(table_id);
+
+	if (!tbl) {
+		filter_dbg(FERR, "%s Invalid TableID %d\n", __func__, table_id);
+		return TNS_ERR_INVALID_TBL_ID;
+	}
+
+	if (*index == -1) {
+		*index = find_first_zero_bit(tbl->ddata[node].bitmap,
+					     tbl->sdata.depth);
+
+		if (*index < 0 || *index >= tbl->sdata.depth)
+			err = -ENOSPC;
+		else
+			__set_bit(*index, tbl->ddata[node].bitmap);
+
+		return err;
+	} else if (*index < 0 || *index >= tbl->sdata.depth) {
+		filter_dbg(FERR, "%s Out of bound index %d requested[0...%d]\n",
+			   __func__, *index, tbl->sdata.depth);
+		return TNS_ERR_MAC_FILTER_INVALID_ENTRY;
+	}
+	if (test_and_set_bit(*index, tbl->ddata[node].bitmap))
+		filter_dbg(FDEBUG, "%s Entry Already exists\n", __func__);
+
+	return err;
+}
+
+void free_table_index(int node, int table_id, int index)
+{
+	struct tns_table_s *tbl = get_table_information(table_id);
+
+	if (!tbl) {
+		filter_dbg(FERR, "%s Invalid TableID %d\n", __func__, table_id);
+		return;
+	}
+	if (index < 0 || index >= tbl->sdata.depth) {
+		filter_dbg(FERR, "%s Invalid Index %d Max Limit %d\n",
+			   __func__, index, tbl->sdata.depth);
+		return;
+	}
+
+	__clear_bit(index, tbl->ddata[node].bitmap);
+}
diff --git a/drivers/net/ethernet/cavium/thunder/tbl_access.h b/drivers/net/ethernet/cavium/thunder/tbl_access.h
new file mode 100644
index 0000000..c098410
--- /dev/null
+++ b/drivers/net/ethernet/cavium/thunder/tbl_access.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 Cavium, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef __TBL_ACCESS_H__
+#define __TBL_ACCESS_H__
+
+#define TNS_MAX_TABLE	8
+
+enum {
+	TNS_TBL_TYPE_DT,
+	TNS_TBL_TYPE_HT,
+	TNS_TBL_TYPE_TT,
+	TNS_TBL_TYPE_MAX
+};
+
+struct table_static_s {
+	u8 tbl_type;
+	u8 tbl_id;
+	u8 valid;
+	u8 rsvd;
+	u16 key_size;
+	u16 data_size;
+	u16 data_width;
+	u16 key_width;
+	u32 depth;
+	u64 key_base_addr;
+	u64 data_base_addr;
+	u8 tbl_name[32];
+};
+
+struct table_dynamic_s {
+	unsigned long *bitmap;
+};
+
+struct tns_table_s {
+	struct table_static_s sdata;
+	struct table_dynamic_s ddata[MAX_NUMNODES];
+};
+
+enum {
+	MAC_FILTER_TABLE = 102,
+	VLAN_FILTER_TABLE = 103,
+	MAC_EVIF_TABLE = 140,
+	VLAN_EVIF_TABLE = 201,
+	PORT_CONFIG_TABLE = 202,
+	TABLE_ID_END
+};
+
+extern struct tns_table_s	tbl_info[TNS_MAX_TABLE];
+
+struct filter_keymask_s {
+	u8 is_valid;
+	u64 key_value;
+};
+
+#endif /* __TBL_ACCESS_H__ */
-- 
1.8.3.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ