net/netfilter/nf_flow_table_path.c

Source file repositories/reference/linux-study-clean/net/netfilter/nf_flow_table_path.c

File Facts

System
Linux kernel
Corpus path
net/netfilter/nf_flow_table_path.c
Extension
.c
Size
9582 bytes
Lines
351
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct nft_forward_info {
	const struct net_device *indev;
	const struct net_device *outdev;
	struct id {
		__u16	id;
		__be16	proto;
	} encap[NF_FLOW_TABLE_ENCAP_MAX];
	u8 num_encaps;
	struct flow_offload_tunnel tun;
	u8 num_tuns;
	u8 ingress_vlans;
	u8 h_source[ETH_ALEN];
	u8 h_dest[ETH_ALEN];
	bool needs_gso_segment;
	enum flow_offload_xmit_type xmit_type;
};

static int nft_dev_path_info(const struct net_device_path_stack *stack,
			     struct nft_forward_info *info,
			     unsigned char *ha, struct nf_flowtable *flowtable)
{
	const struct net_device_path *path;
	int i;

	memcpy(info->h_dest, ha, ETH_ALEN);

	for (i = 0; i < stack->num_paths; i++) {
		path = &stack->path[i];
		switch (path->type) {
		case DEV_PATH_ETHERNET:
		case DEV_PATH_DSA:
		case DEV_PATH_VLAN:
		case DEV_PATH_PPPOE:
		case DEV_PATH_TUN:
			info->indev = path->dev;
			if (is_zero_ether_addr(info->h_source))
				memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);

			if (path->type == DEV_PATH_ETHERNET)
				break;
			if (path->type == DEV_PATH_DSA) {
				i = stack->num_paths;
				break;
			}

			/* DEV_PATH_VLAN, DEV_PATH_PPPOE and DEV_PATH_TUN */
			if (path->type == DEV_PATH_TUN) {
				if (info->num_tuns)
					return -1;

				info->tun.src_v6 = path->tun.src_v6;
				info->tun.dst_v6 = path->tun.dst_v6;
				info->tun.l3_proto = path->tun.l3_proto;
				info->num_tuns++;
			} else {
				if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX)
					return -1;

				info->encap[info->num_encaps].id =
					path->encap.id;
				info->encap[info->num_encaps].proto =
					path->encap.proto;
				info->num_encaps++;
			}
			if (path->type == DEV_PATH_PPPOE) {
				memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN);
				info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT;
				info->needs_gso_segment = 1;
			}
			break;
		case DEV_PATH_BRIDGE:
			if (is_zero_ether_addr(info->h_source))
				memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN);

			switch (path->bridge.vlan_mode) {
			case DEV_PATH_BR_VLAN_UNTAG_HW:
				if (info->num_encaps == 0)
					return -1;

				info->ingress_vlans |= BIT(info->num_encaps - 1);
				break;
			case DEV_PATH_BR_VLAN_TAG:
				if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX)
					return -1;

				info->encap[info->num_encaps].id = path->bridge.vlan_id;
				info->encap[info->num_encaps].proto = path->bridge.vlan_proto;
				info->num_encaps++;
				break;
			case DEV_PATH_BR_VLAN_UNTAG:

Annotation

Implementation Notes