Skip to content

Commit

Permalink
Add fdb flush lua script v2 with switch id support (#329)
Browse files Browse the repository at this point in the history
if you flush fdb on one switch when multiple switches are present in syncd currently it will flush fdb entries from all switches, this change will add support per switch, then previous version can be removed.
  • Loading branch information
kcudnik authored Mar 12, 2020
1 parent 7cc1c5a commit 8b54767
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 0 deletions.
43 changes: 43 additions & 0 deletions common/fdb_flush.v2.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
redis.log(redis.LOG_NOTICE, "swid", KEYS[1], "bvid", KEYS[2], "port", KEYS[3], "type", KEYS[4])

local swid = KEYS[1]
local bvid = KEYS[2]
local port = KEYS[3]
local type = KEYS[4]

if swid == "oid:0x0" then swid = "" end
if bvid == "oid:0x0" then bvid = "" end
if port == "oid:0x0" then port = "" end

redis.log(redis.LOG_NOTICE, "swid '" .. swid .. "' bvid '" .. bvid .. "' port '" .. port .. "' type '" .. type .. "'")

local pattern = "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY:*bvid*" .. bvid .. "*switch_id*" .. swid .. "*";
local keys = redis.call('KEYS', pattern);
local n = table.getn(keys)

redis.log(redis.LOG_WARNING, "n = " .. n .. " pattern", pattern)

for i = 1, n do

-- redis.log(redis.LOG_WARNING, "k = ", keys[i])

if port == "" and type == "" then
redis.call('DEL', keys[i])
elseif port == "" and type ~= "" then
local etype = redis.call('HGET', keys[i], "SAI_FDB_ENTRY_ATTR_TYPE");
if etype == type then
redis.call('DEL', keys[i])
end
elseif port ~= "" and type == "" then
local eport = redis.call('HGET', keys[i], "SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID");
if eport == port then
redis.call('DEL', keys[i])
end
else -- port =~ "" and type =~ ""
local etype = redis.call('HGET', keys[i], "SAI_FDB_ENTRY_ATTR_TYPE");
local eport = redis.call('HGET', keys[i], "SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID");
if eport == port and etype == type then
redis.call('DEL', keys[i])
end
end
end
1 change: 1 addition & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ tests_SOURCES = redis_ut.cpp \
selectable_priority.cpp \
warm_restart_ut.cpp \
redis_multi_db_ut.cpp \
fdb_flush.cpp \
main.cpp

tests_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST) $(LIBNL_CFLAGS)
Expand Down
242 changes: 242 additions & 0 deletions tests/fdb_flush.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
#include "gtest/gtest.h"

#include "common/dbconnector.h"
#include "common/producertable.h"
#include "common/consumertable.h"
#include "common/redisapi.h"
#include "common/redisclient.h"

#include <iostream>
#include <memory>
#include <thread>
#include <algorithm>

using namespace std;
using namespace swss;

static std::string tableName = "ASIC_STATE";

static void clear()
{
DBConnector db("TEST_DB", 0, true);

RedisReply r(&db, "FLUSHALL", REDIS_REPLY_STATUS);

r.checkStatusOK();
}

static void insert(
uint64_t switchId,
uint64_t bvId,
uint64_t portId,
unsigned char mac,
bool isStatic)
{
DBConnector db("TEST_DB", 0, true);

ProducerTable producer(&db, tableName);
ConsumerTable consumer(&db, tableName);

// "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\"oid:0x26000000000545\",\"mac\":\"4A:A8:7B:A2:37:1A\",\"switch_id\":\"oid:0x21000000000000\"}"
// "SAI_FDB_ENTRY_ATTR_TYPE" "SAI_FDB_ENTRY_TYPE_DYNAMIC"
// "SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID" "oid:0x3a000000000567"
// "SAI_FDB_ENTRY_ATTR_PACKET_ACTION" "SAI_PACKET_ACTION_FORWARD"

std::vector<FieldValueTuple> values;

char buffer[4000];

sprintf(buffer, "SAI_OBJECT_TYPE_FDB_ENTRY:{\"bvid\":\"oid:0x%lx\",\"mac\":\"00:00:00:00:00:%02X\",\"switch_id\":\"oid:0x%lx\"}", bvId, mac, switchId);

std::string key = buffer;

// printf("key: %s\n", buffer);

char port[1000];

sprintf(port, "oid:0x%lx", portId);

values.emplace_back("SAI_FDB_ENTRY_ATTR_PACKET_ACTION", "SAI_PACKET_ACTION_FORWARD");
values.emplace_back("SAI_FDB_ENTRY_ATTR_TYPE", (isStatic ? "SAI_FDB_ENTRY_TYPE_STATIC" : "SAI_FDB_ENTRY_TYPE_DYNAMIC"));
values.emplace_back("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID", port);

producer.set(key, values, "set");

std::string op;
std::vector<FieldValueTuple> fvs;

consumer.pop(key, op, fvs);
}

static size_t count()
{
DBConnector db("TEST_DB", 0, true);

RedisClient rc(&db);

auto keys = rc.keys("ASIC_STATE:*");

return keys.size();
}

void print()
{
DBConnector db("TEST_DB", 0, true);

RedisClient rc(&db);

auto keys = rc.keys("ASIC_STATE:*");

for (auto&k : keys)
{
printf("K %s\n", k.c_str());

auto hash = rc.hgetall(k);

for (auto&h: hash)
{
printf(" * %s = %s\n", h.first.c_str(), h.second.c_str());
}
}
}

static std::string sOid(
uint64_t oid)
{
char buffer[100];

sprintf(buffer, "oid:0x%lx", oid);

return buffer;
}

static void populate()
{
clear();

insert(0x21000000000000, 0x26000000000001, 0x3a000000000001, 1, true);
insert(0x21000000000000, 0x26000000000002, 0x3a000000000002, 2, false);

insert(0x121000000000001, 0x126000000000003, 0x13a000000000003, 3, true);
insert(0x121000000000001, 0x126000000000004, 0x13a000000000004, 4, false);
}

static void exec(
uint64_t switchId,
uint64_t bvId,
uint64_t portId,
std::string type)
{
DBConnector db("TEST_DB", 0, true);

populate();
//print();

auto fdbFlushLuaScript = swss::readTextFile("./common/fdb_flush.v2.lua");

auto sha = swss::loadRedisScript(&db, fdbFlushLuaScript);

swss::RedisCommand command;

command.format(
"EVALSHA %s 4 %s %s %s %s",
sha.c_str(),
sOid(switchId).c_str(), // 0x0 == any
sOid(bvId).c_str(), // 0x0 == any
sOid(portId).c_str(), // 0x0 == any
type.c_str()); //(0 ? "SAI_FDB_ENTRY_TYPE_STATIC" : "SAI_FDB_ENTRY_TYPE_DYNAMIC")); // empty == any

swss::RedisReply r(&db, command);
}

static void mac(unsigned char m, bool is)
{
DBConnector db("TEST_DB", 0, true);

RedisClient rc(&db);

char buffer[100];

sprintf(buffer, "*SAI_OBJECT_TYPE_FDB_ENTRY:*\"mac\":\"00:00:00:00:00:%02X\"*", m);

auto keys = rc.keys(buffer);

if (is)
{
EXPECT_EQ(keys.size(), 1);
return;
}

EXPECT_EQ(keys.size(), 0);
}

TEST(Fdb, flush)
{
DBConnector db("TEST_DB", 0, true);

exec(0,0,0, "");

EXPECT_EQ(count(), 0);

exec(0x21000000000000,0,0, "");

mac(1,0);
mac(2,0);
mac(3,1);
mac(4,1);

exec(0x21000000000000,0x26000000000001,0, "");

mac(1,0);
mac(2,1);
mac(3,1);
mac(4,1);

exec(0x21000000000000,0,0x3a000000000001, "");

mac(1,0);
mac(2,1);
mac(3,1);
mac(4,1);

exec(0x21000000000000,0,0, "SAI_FDB_ENTRY_TYPE_STATIC");

mac(1,0);
mac(2,1);
mac(3,1);
mac(4,1);

exec(0x21000000000000,0x26000000000001,0x3a000000000001, "SAI_FDB_ENTRY_TYPE_STATIC");

mac(1,0);
mac(2,1);
mac(3,1);
mac(4,1);

exec(0x121000000000001,0,0, "");

mac(1,1);
mac(2,1);
mac(3,0);
mac(4,0);

exec(0,0,0, "SAI_FDB_ENTRY_TYPE_STATIC");

mac(1,0);
mac(2,1);
mac(3,0);
mac(4,1);

exec(0,0,0, "SAI_FDB_ENTRY_TYPE_DYNAMIC");

mac(1,1);
mac(2,0);
mac(3,1);
mac(4,0);

//insert(0x21000000000000, 0x26000000000001, 0x3a000000000001, 1, true);
//insert(0x21000000000000, 0x26000000000002, 0x3a000000000002, 2, false);
//insert(0x121000000000001, 0x126000000000003, 0x13a000000000003, 3, true);
//insert(0x121000000000001, 0x126000000000004, 0x13a000000000004, 4, false);
}

0 comments on commit 8b54767

Please sign in to comment.