Skip to content

SWBus to swss‐common bridge

r12f edited this page Oct 27, 2024 · 2 revisions

Overview

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 to swbusd and anywhere outside.

Service path for swss-common channels

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

Channel initialization

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

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

Consumer channels are incoming channels that the service will use to receive messages from other services. For each consumer channel, we need to define:

  1. The service path defined at service level, so swss-api can use it to specify where the message is coming from.
  2. 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.

Message routing and processing

Outgoing message processing

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
Loading

Incoming message dispatching

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
Loading

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.