-
Notifications
You must be signed in to change notification settings - Fork 5
SWBus to swss‐common bridge
To help unify the communication channel for all the resources within a service, swbus-api-swss
crate provides a message filter that adapts the swbus message to the swss-common message.
NOTE: Message filter is only available within
swbus-api
, hence it is in-service only and will not be exposed toswbusd
and anywhere outside.
The swss-common channels are usually defined as singled-direction channels but works in pair, such as: ProducerStateTable and ConsumerStateTable. Both of them are sharing the same underlying redis key/entry but acting as producer and consumer respectively.
Hence, for each pair of swss-common channels, we can define a single service path for communication and use them in both sides of services if needed. For example:
Node Locator | Service Locator | Resource Locator | ||||
---|---|---|---|---|---|---|
Region ID | Cluster ID | Node Id | Service Type | Service Id | Resource Type | Resource Id |
region-a | switch-cluster-a | 10.0.0.1-dpu0 | redis | APPL.SOME_TABLE | data | some_key:some_subkey |
Same as the usage of swss-common, while the service starts to launch, we will create the list of channels that the service will use. These channels will be registered into the SwbusSwssFilter with metadata, so we can use them for message routing later.
Producer channels are outgoing channels that the service will use to send messages to other services. For reach producer channel, we need to have the service path defined at service level, so swss-api
can use it to route the message to the correct destination.
let redis = Redis::start();
let db = DbConnector::new_unix(0, &redis.sock, 0);
let pst = ProducerStateTable::new(db.clone(), "my_table");
let svc_path = ServicePath::with_service("region-a", "switch-cluster-a", "10.0.0.1-dpu0", "redis", "APPL.my_table");
let swss_filter = SwbusSwssFilter::with_producer_state(svc_path, pst).build();
// Register the filter to the SwbusRuntime.
Consumer channels are incoming channels that the service will use to receive messages from other services. For each consumer channel, we need to define:
- The service path defined at service level, so
swss-api
can use it to specify where the message is coming from. - The callback function that used for creating the destination service path, when a message is received from the consumer channel, so
swss-api
can use it to route the message to the correct destination.
let redis = Redis::start();
let db = DbConnector::new_unix(0, &redis.sock, 0);
let cst = ConsumerStateTable::new(db.clone(), "my_table", None, None);
let svc_path = ServicePath::with_service("region-a", "switch-cluster-a", "10.0.0.1-dpu0", "redis", "APPL.my_table");
let swss_filter = SwbusSwssFilter::with_consumer_state(svc_path, cst, |msg| {
// Create the destination service path based on the message
// For example, the message is coming from the same service
ServicePath::with_service("region-a", "switch-cluster-a", "10.0.0.1-dpu0", "hamgrd", "0", "hascope", msg.get_key())
}).build();
// Register the filter to the SwbusRuntime.
When a resource sends out the message producer channel using swbus-api, the message will have the full serivce path. Message filter within the swbus-api will use the service path to find the corresponding producer channel and send the message to the channel.
Once the producer channel set
function is called, the swss message filter will generate the ACK message and send it back to the service, which indicates the message is successfully written in the channel.
If sender didn't receive the ACK message and timed out, it should retry the message sending.
sequenceDiagram
participant R as Resource
participant RT as SwbusRuntime
participant F as SwbusSwssFilter
participant PST as ProducerStateTable
participant DB as Redis
R->>RT: Send swbus message
RT->>F: Use destination service path<br>to find the message filter
F->>PST: Convert swbus message to<br>producer channel set call
PST->>DB: Update database with<br>the message info
alt is sucessful
F->>RT: Send ACK message back<br>to the sender<br>(SWBUS_ERROR_CODE_OK)
RT->>R: Receive ACK message
else is failed
F->>RT: Send FAIL message message back<br>to the sender<br>(SWBUS_ERROR_CODE_FAIL)
RT->>R: Receive FAIL message
end
When SwbusSwssFilter receives a message from the consumer channel, it will use the callback function to create the destination service path based on the message and send it to SwbusRuntime to forward the message properly.
sequenceDiagram
participant R as Resource
participant RT as SwbusRuntime
participant F as SwbusSwssFilter
participant CST as ConsumerStateTable
participant DB as Redis
DB->>F: Receive message from<br>consumer channel
F->>F: Use callback function to<br>create destination service path
F->>RT: Forward the message to<br>the destination service path
RT->>R: Receive the message
In the path of receiving, we don't need to respond the ACK message back to the SwbusSwssFilter, since there is no retry mechanism for the incoming message. If any ACK message is returned, it will be ignored by the SwbusSwssFilter.