-
Notifications
You must be signed in to change notification settings - Fork 551
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[vog/systemlag] Voq lagid allocator (#1603)
What I did Defined class for lag id allocator and added lua script for allocating/freeing lag id in atomic fashion Why I did it For portchannels in VOQ based chassis systems we need unique lag id across the system. The lag id (aka system port aggreggator id) is allocated during portchannel creation. The changes are for a class for lag id allocation in atomic fashion. The LAG ID is allocated from central chassis app db. A lua script loaded in the redis at the time of lag id allocator instantiation ensures allocating unique lag id when multiple clients requests for lag id simultaneously. Ref: VOQ LAG HLD PR: sonic-net/SONiC#697
- Loading branch information
1 parent
b0c2a74
commit 1951365
Showing
3 changed files
with
228 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#include "lagid.h" | ||
|
||
LagIdAllocator::LagIdAllocator( | ||
_In_ DBConnector* chassis_app_db) | ||
{ | ||
SWSS_LOG_ENTER(); | ||
|
||
m_dbConnector = chassis_app_db; | ||
|
||
// Load lua script to allocate system lag id. This lua script ensures allocation | ||
// of unique system lag id from global chassis app db in atomic fashion when allocation | ||
// is requested by different asic instances simultaneously | ||
|
||
string luaScript = loadLuaScript("lagids.lua"); | ||
m_shaLagId = loadRedisScript(m_dbConnector, luaScript); | ||
} | ||
|
||
int32_t LagIdAllocator::lagIdAdd( | ||
_In_ const string &pcname, | ||
_In_ int32_t lag_id) | ||
{ | ||
SWSS_LOG_ENTER(); | ||
|
||
// No keys | ||
vector<string> keys; | ||
|
||
vector<string> args; | ||
args.push_back("add"); | ||
args.push_back(pcname); | ||
args.push_back(to_string(lag_id)); | ||
|
||
set<string> ret = runRedisScript(*m_dbConnector, m_shaLagId, keys, args); | ||
|
||
if (!ret.empty()) | ||
{ | ||
// We expect only one value in the set returned | ||
|
||
auto rv_lag_id = ret.begin(); | ||
|
||
return (stoi(*rv_lag_id)); | ||
} | ||
|
||
return LAG_ID_ALLOCATOR_ERROR_DB_ERROR; | ||
} | ||
|
||
int32_t LagIdAllocator::lagIdDel( | ||
_In_ const string &pcname) | ||
{ | ||
SWSS_LOG_ENTER(); | ||
|
||
// No keys | ||
vector<string> keys; | ||
|
||
vector<string> args; | ||
args.push_back("del"); | ||
args.push_back(pcname); | ||
|
||
set<string> ret = runRedisScript(*m_dbConnector, m_shaLagId, keys, args); | ||
|
||
if (!ret.empty()) | ||
{ | ||
// We expect only one value in the set returned | ||
|
||
auto rv_lag_id = ret.begin(); | ||
|
||
return (stoi(*rv_lag_id)); | ||
} | ||
|
||
return LAG_ID_ALLOCATOR_ERROR_DB_ERROR; | ||
} | ||
|
||
int32_t LagIdAllocator::lagIdGet( | ||
_In_ const string &pcname) | ||
{ | ||
SWSS_LOG_ENTER(); | ||
|
||
// No keys | ||
vector<string> keys; | ||
|
||
vector<string> args; | ||
args.push_back("get"); | ||
args.push_back(pcname); | ||
|
||
set<string> ret = runRedisScript(*m_dbConnector, m_shaLagId, keys, args); | ||
|
||
if (!ret.empty()) | ||
{ | ||
// We expect only one value in the set returned | ||
|
||
auto rv_lag_id = ret.begin(); | ||
|
||
return (stoi(*rv_lag_id)); | ||
} | ||
|
||
return LAG_ID_ALLOCATOR_ERROR_DB_ERROR; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#ifndef SWSS_LAGID_H | ||
#define SWSS_LAGID_H | ||
|
||
#include "dbconnector.h" | ||
#include "sal.h" | ||
#include "schema.h" | ||
#include "redisapi.h" | ||
|
||
using namespace swss; | ||
using namespace std; | ||
|
||
#define LAG_ID_ALLOCATOR_ERROR_DELETE_ENTRY_NOT_FOUND 0 | ||
#define LAG_ID_ALLOCATOR_ERROR_TABLE_FULL -1 | ||
#define LAG_ID_ALLOCATOR_ERROR_GET_ENTRY_NOT_FOUND -2 | ||
#define LAG_ID_ALLOCATOR_ERROR_INVALID_OP -3 | ||
#define LAG_ID_ALLOCATOR_ERROR_DB_ERROR -4 | ||
|
||
class LagIdAllocator | ||
{ | ||
public: | ||
|
||
LagIdAllocator( | ||
_In_ DBConnector* chassis_app_db); | ||
|
||
public: | ||
|
||
int32_t lagIdAdd( | ||
_In_ const string &pcname, | ||
_In_ int32_t lag_id); | ||
|
||
int32_t lagIdDel( | ||
_In_ const string &pcname); | ||
|
||
int32_t lagIdGet( | ||
_In_ const string &pcname); | ||
|
||
private: | ||
|
||
DBConnector* m_dbConnector; | ||
|
||
string m_shaLagId; | ||
}; | ||
|
||
#endif // SWSS_LAGID_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
-- KEYS - None | ||
-- ARGV[1] - operation (add/del/get) | ||
-- ARGV[2] - lag name | ||
-- ARGV[3] - current lag id (for "add" operation only) | ||
|
||
-- return lagid if success for "add"/"del" | ||
-- return 0 if lag does not exist for "del" | ||
-- return -1 if lag table full for "add" | ||
-- return -2 if lag does not exist for "get" | ||
-- return -3 if invalid operation | ||
|
||
local op = ARGV[1] | ||
local pcname = ARGV[2] | ||
|
||
local lagid_start = tonumber(redis.call("get", "SYSTEM_LAG_ID_START")) | ||
local lagid_end = tonumber(redis.call("get", "SYSTEM_LAG_ID_END")) | ||
|
||
if op == "add" then | ||
|
||
local plagid = tonumber(ARGV[3]) | ||
|
||
local dblagid = redis.call("hget", "SYSTEM_LAG_ID_TABLE", pcname) | ||
|
||
if dblagid then | ||
dblagid = tonumber(dblagid) | ||
if plagid == 0 then | ||
-- no lagid proposed. Return the existing lagid | ||
return dblagid | ||
end | ||
end | ||
|
||
-- lagid allocation request with a lagid proposal | ||
if plagid >= lagid_start and plagid <= lagid_end then | ||
if plagid == dblagid then | ||
-- proposed lagid is same as the lagid in database | ||
return plagid | ||
end | ||
-- proposed lag id is different than that in database OR | ||
-- the portchannel does not exist in the database | ||
-- If proposed lagid is available, return the same proposed lag id | ||
if redis.call("sismember", "SYSTEM_LAG_ID_SET", tostring(plagid)) == 0 then | ||
redis.call("sadd", "SYSTEM_LAG_ID_SET", tostring(plagid)) | ||
redis.call("srem", "SYSTEM_LAG_ID_SET", tostring(dblagid)) | ||
redis.call("hset", "SYSTEM_LAG_ID_TABLE", pcname, tostring(plagid)) | ||
return plagid | ||
end | ||
end | ||
|
||
local lagid = lagid_start | ||
while lagid <= lagid_end do | ||
if redis.call("sismember", "SYSTEM_LAG_ID_SET", tostring(lagid)) == 0 then | ||
redis.call("sadd", "SYSTEM_LAG_ID_SET", tostring(lagid)) | ||
redis.call("srem", "SYSTEM_LAG_ID_SET", tostring(dblagid)) | ||
redis.call("hset", "SYSTEM_LAG_ID_TABLE", pcname, tostring(lagid)) | ||
return lagid | ||
end | ||
lagid = lagid + 1 | ||
end | ||
|
||
return -1 | ||
|
||
end | ||
|
||
if op == "del" then | ||
|
||
if redis.call("hexists", "SYSTEM_LAG_ID_TABLE", pcname) == 1 then | ||
local lagid = redis.call("hget", "SYSTEM_LAG_ID_TABLE", pcname) | ||
redis.call("srem", "SYSTEM_LAG_ID_SET", lagid) | ||
redis.call("hdel", "SYSTEM_LAG_ID_TABLE", pcname) | ||
return tonumber(lagid) | ||
end | ||
|
||
return 0 | ||
|
||
end | ||
|
||
if op == "get" then | ||
|
||
if redis.call("hexists", "SYSTEM_LAG_ID_TABLE", pcname) == 1 then | ||
local lagid = redis.call("hget", "SYSTEM_LAG_ID_TABLE", pcname) | ||
return tonumber(lagid) | ||
end | ||
|
||
return -2 | ||
|
||
end | ||
|
||
return -3 |