net/hsr/hsr_framereg.c
Source file repositories/reference/linux-study-clean/net/hsr/hsr_framereg.c
File Facts
- System
- Linux kernel
- Corpus path
net/hsr/hsr_framereg.c- Extension
.c- Size
- 24962 bytes
- Lines
- 898
- Domain
- Networking Core
- Bucket
- Sockets, Protocols, Packet Path, And Network Policy
- Inferred role
- Networking Core: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.
- Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
kunit/visibility.hlinux/if_ether.hlinux/etherdevice.hlinux/slab.hlinux/rculist.hhsr_main.hhsr_framereg.hhsr_netlink.h
Detected Declarations
function Authorfunction hsr_addr_is_selffunction list_for_each_entry_rcufunction hsr_is_node_in_dbfunction hsr_create_self_nodefunction hsr_del_self_nodefunction hsr_free_nodefunction hsr_free_node_rcufunction hsr_lock_seq_out_pairfunction hsr_unlock_seq_out_pairfunction hsr_del_nodesfunction list_for_each_entry_safefunction prp_handle_san_framefunction lockdep_is_heldfunction prp_update_san_infofunction list_for_each_entry_rcufunction hsr_seq_block_is_oldfunction hsr_forget_seq_blockfunction timefunction hsr_handle_sup_framefunction xa_for_eachfunction hsr_addr_subst_sourcefunction targetfunction hsr_register_frame_infunction hsr_get_seq_blockfunction hsr_register_frame_outfunction prp_register_frame_outfunction HSR_LIFE_CHECK_INTERVALfunction hsr_prune_proxy_nodesfunction fill_last_seq_nrsfunction hsr_get_node_data
Annotated Snippet
lockdep_is_held(&hsr->list_lock)) {
if (ether_addr_equal(node->macaddress_A, addr))
goto out;
if (ether_addr_equal(node->macaddress_B, addr))
goto out;
}
list_add_tail_rcu(&new_node->mac_list, node_db);
spin_unlock_bh(&hsr->list_lock);
return new_node;
out:
spin_unlock_bh(&hsr->list_lock);
kfree(new_node->block_buf);
free:
kfree(new_node);
return node;
}
void prp_update_san_info(struct hsr_node *node, bool is_sup)
{
if (!is_sup)
return;
node->san_a = false;
node->san_b = false;
}
/* Get the hsr_node from which 'skb' was sent.
*/
struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db,
struct sk_buff *skb, bool is_sup,
enum hsr_port_type rx_port)
{
struct hsr_priv *hsr = port->hsr;
struct hsr_node *node;
struct ethhdr *ethhdr;
struct prp_rct *rct;
bool san = false;
if (!skb_mac_header_was_set(skb))
return NULL;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
list_for_each_entry_rcu(node, node_db, mac_list) {
if (ether_addr_equal(node->macaddress_A, ethhdr->h_source)) {
if (hsr->proto_ops->update_san_info)
hsr->proto_ops->update_san_info(node, is_sup);
return node;
}
if (ether_addr_equal(node->macaddress_B, ethhdr->h_source)) {
if (hsr->proto_ops->update_san_info)
hsr->proto_ops->update_san_info(node, is_sup);
return node;
}
}
/* Check if required node is not in proxy nodes table */
list_for_each_entry_rcu(node, &hsr->proxy_node_db, mac_list) {
if (ether_addr_equal(node->macaddress_A, ethhdr->h_source)) {
if (hsr->proto_ops->update_san_info)
hsr->proto_ops->update_san_info(node, is_sup);
return node;
}
}
/* Everyone may create a node entry, connected node to a HSR/PRP
* device.
*/
if (ethhdr->h_proto == htons(ETH_P_PRP) ||
ethhdr->h_proto == htons(ETH_P_HSR)) {
/* Check if skb contains hsr_ethhdr */
if (skb->mac_len < sizeof(struct hsr_ethhdr))
return NULL;
} else {
rct = skb_get_PRP_rct(skb);
if (!rct && rx_port != HSR_PT_MASTER)
san = true;
}
return hsr_add_node(hsr, node_db, ethhdr->h_source, san, rx_port);
}
static bool hsr_seq_block_is_old(struct hsr_seq_block *block)
{
unsigned long expiry = msecs_to_jiffies(HSR_ENTRY_FORGET_TIME);
return time_is_before_jiffies(block->time + expiry);
}
static void hsr_forget_seq_block(struct hsr_node *node,
Annotation
- Immediate include surface: `kunit/visibility.h`, `linux/if_ether.h`, `linux/etherdevice.h`, `linux/slab.h`, `linux/rculist.h`, `hsr_main.h`, `hsr_framereg.h`, `hsr_netlink.h`.
- Detected declarations: `function Author`, `function hsr_addr_is_self`, `function list_for_each_entry_rcu`, `function hsr_is_node_in_db`, `function hsr_create_self_node`, `function hsr_del_self_node`, `function hsr_free_node`, `function hsr_free_node_rcu`, `function hsr_lock_seq_out_pair`, `function hsr_unlock_seq_out_pair`.
- Atlas domain: Networking Core / Sockets, Protocols, Packet Path, And Network Policy.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.