# An In-Network Cooperative Storage Schema Based on Neighbor Offloading in a Programmable Data Plane
## 4 In-Network Cooperative Storage Mechanism  
### Neighbor Selection Mechanism  
LNMRS is usually deployed at the edge of the network and close to the forwarding devices, and maintains local ID-locator pairs. As a result, LNMRS may be more efficient or provide on-site service for users. LNMRS is also a hierarchical service system with a distributed architecture, which can synchronize part of the mapping of the ID and NA to GNMRS to be accessed globally [35]. The in-network storage service node registers the mapping storage service ID and its NA to LNMRS on startup. Considering the locality of the storage and a fast response, the neighbor nodes should be selected from nearby nodes. In addition, LNMRS is a suitable choice to select candidate neighbors by resolving the service ID. In the case of the storage, congestion occurs where the transmission bandwidth is limited or storage IO is insufficient. Only considering link bandwidth or node storage capability is not enough, especially in high throughput traffic scenarios. Thus, we combine the two pieces of information as the criteria for node selection. The load information exchange packet contains the current input interface's total available input and output bandwidth (interface_total_bandwidth), and the current node's available writing throughput (w\({}_{\text{IO}}\)) and message identification. When the neighbor node receives a load information exchange packet, it will respond with an ACK. Based on the received ACK time, we estimate the latency (RTT). RTT is computed as an exponentially weighted moving average (EWMA) of RTT in Equation (1). \(rtt_{i}\) is the time from the transmission of the \(i\)-th packet until receipt of the ACK of the \(i\)-th packet. \(RTT_{i}\) is estimated as the average round trip time after the \(i\)-th packet. We assume \(RTT_{0}=0\) and \(\alpha=0.125\) (which is a typical value in TCP [36]). \[RTT(k)_{i}=\ (1-\alpha)\ *\ RTT(k)_{i-1}+\ \alpha*rtt(k)_{i} \tag{1}\]  
The neighbor node's weight is computed based on the neighbor's interface_total_band width and available writing throughput in Equation (2). \[\text{neighbor}_{\text{weight(k)}}= \tag{2}\] \[(\beta*bandwidth(k)\ *\ RTT(k)\ +\ (1-\beta)\ *\ w(k)_{IO}*RTT(k))/2\]  
The weight of the node itself is computed in Equation (3) based on the node's available writing throughput and the average RTT of all neighbor nodes. \[\text{self\_weight}=(w_{IO}*average\_RTT)/2 \tag{3}\]Because the chunk data needs to be shifted from nodes with heavy load to those with less load, determining when to shift the load is important. We define a normalized value \(\gamma\) in Equation (4). \[\gamma= \tag{4}\] \[\frac{self\_weight(i)-\min(weight(k),k\in neighbors\_list|i)}{max(weight(k), k\in neighbor|i)-\min(weight(k),k\in neighbors\_list|i)}\]  
If \(\gamma\) is smaller than the defined threshold, the chunk data should be offloaded to its neighbors; otherwise, the traffic is not offloaded to its neighbors and it is better to store the chunk itself. We defined the threshold as 0.5 in simulation. When the threshold is set to 0, it means it has no cooperative storage mechanism and is just like a common node. As shown in Algorithm 1, when the node is in the cooperative state, it sorts the neighbors' weight and selects a certain number of nodes (N) that exceed the current node's weight value as its final offloaded targets. Then, the traffic is split by the data chunk ID to these selected targets according to their weights.