OVS2.5.0 Source Analysis DataPath Action Analysis (1)

Source: Internet
Author: User
Tags goto

The action supported by the OVS DP is defined in the Do_execute_actions function, and the supported actions include: Ovs_action_attr_output, Ovs_action_attr_userspace, Ovs_ Action_attr_hash, Ovs_action_attr_push_mpls, Ovs_action_attr_pop_mpls, Ovs_action_attr_push_vlan, OVS_ACTION_ATTR_ Pop_vlan, Ovs_action_attr_recirc, Ovs_action_attr_set, ovs_action_attr_set_masked, OVS_ACTION_ATTR_SET_TO_MASKED, Ovs_action_attr_sample, Ovs_action_attr_ct. To complete the analysis of these actions in this series, the output has already been introduced prior to the introduction of the DataPath mainstream, and is no longer covered.

The processing function of Ovs_action_attr_userspace is the Output_userspace function, which is analyzed as a portal by this function.

1. Output_userspace function

static int output_userspace (struct datapath *dp, struct sk_buff *skb, struct sw_flow_key *key, const struct NLATTR
	*attr, const struct NLATTR *actions, int actions_len) {struct Ip_tunnel_info info;
	struct Dp_upcall_info upcall;
	const struct NLATTR *a;

	int rem;
	memset (&upcall, 0, sizeof (upcall));         Upcall.cmd = ovs_packet_cmd_action;

	Encapsulate Upcall Object Upcall.mru = OVS_CB (SKB)->mru;	  for (a = Nla_data (attr), rem = Nla_len (attr); rem > 0;
			Get information about userspace action A = Nla_next (A, &rem)) {switch (Nla_type (a)) {case Ovs_userspace_attr_userdata:
			Upcall.userdata = A;

		Break
			Case OVS_USERSPACE_ATTR_PID:upcall.portid = Nla_get_u32 (a);

		Break

			Case Ovs_userspace_attr_egress_tun_port: {/* Get out tunnel info. */struct Vport *vport;
			Vport = Ovs_vport_rcu (DP, NLA_GET_U32 (a));

				if (vport) {int err;
				Upcall.egress_tun_info = &info; Err = Ovs_vport_get_egress_tun_info (Vport, SKB, &upcall);
			if (err) upcall.egress_tun_info = NULL;
		} break;
			} case Ovs_userspace_attr_actions: {/* Include actions. */upcall.actions = actions;
			Upcall.actions_len = Actions_len;
		Break }}/* End of switch.    */} return Ovs_dp_upcall (DP, SKB, key, &upcall); Upcall}
2. Ovs_dp_upcall function

int Ovs_dp_upcall (struct datapath *dp, struct sk_buff *skb,
		  const struct Sw_flow_key *key,
		  const struct DP_UPCALL _info *upcall_info)
{
	struct dp_stats_percpu *stats;
	int err;

	if (Upcall_info->portid = = 0) {
		err =-enotconn;
		goto err;
	}

	if (!SKB_IS_GSO (SKB))
		err = Queue_userspace_packet (DP, SKB, key, upcall_info);
	else
		err = Queue_gso_packets (DP, SKB, key, upcall_info);
	if (err)
		goto err;

	return 0;

ERR:
	stats = this_cpu_ptr (DP->STATS_PERCPU);

	U64_stats_update_begin (&STATS->SYNCP);
	stats->n_lost++;
	U64_stats_update_end (&STATS->SYNCP);

	return err;
}
3. Queue_userspace_packet function

static int queue_userspace_packet (struct datapath *dp, struct sk_buff *skb, const struct Sw_flow_key *key, con
	St struct Dp_upcall_info *upcall_info) {struct Ovs_header *upcall;
	struct Sk_buff *nskb = NULL; struct Sk_buff *user_skb = NULL;
	/* To is queued to userspace */struct nlattr *nla; struct Genl_info info = {#ifdef have_genlmsg_new_unicast. Dst_sk = Ovs_dp_get_net (DP)->genl_sock, #endif. Snd_port
	id = Upcall_info->portid,};
	size_t Len;
	unsigned int hlen;

	int err, Dp_ifindex;
	Dp_ifindex = Get_dpifindex (DP);

	if (!dp_ifindex) Return-enodev;
		if (Skb_vlan_tag_present (SKB)) {NSKB = Skb_clone (SKB, gfp_atomic);

		if (!NSKB) Return-enomem;
		NSKB = Vlan_insert_tag_set_proto (NSKB, Nskb->vlan_proto, Skb_vlan_tag_get (NSKB));

		if (!NSKB) Return-enomem;	VLAN_SET_TCI (NSKB, 0);

		Why the TCI 0.
	SKB = NSKB;
		} if (Nla_attr_size (Skb->len) > Ushrt_max) {err =-efbig;
	Goto out; }/* Complete checksum if needed */if (SKB-≫ip_summed = = Checksum_partial && (err = Skb_checksum_help (SKB))) goto out;  /* Older versions of OVS user space enforce alignment of the last * NetLink attribute to Nla_alignto which would require Extensive * padding logic.
	 Only perform zerocopy if padding are not required.
	*/if (Dp->user_features & ovs_dp_f_unaligned) Hlen = Skb_zerocopy_headlen (SKB);

	else Hlen = skb->len;
	Len = Upcall_msg_size (Upcall_info, Hlen);		USER_SKB = Genlmsg_new_unicast (len, &info, gfp_atomic);
		Create Upcall Message Object if (!USER_SKB) {err =-enomem;
	Goto out;
			     } Upcall = Genlmsg_put (user_skb, 0, 0, &dp_packet_genl_family,//dp_packet_genl_family and upcall_info->cmd determine processing functions
	0, Upcall_info->cmd);

	Upcall->dp_ifindex = Dp_ifindex;  Err = Ovs_nla_put_key (key, Key, Ovs_packet_attr_key, false, USER_SKB);

	Upcall Information Object add key bug_on (ERR); if (upcall_info->userdata) __nla_put (USER_SKB, Ovs_packet_attr_userdata,//upcall information object add UserData NLA_len (Upcall_info->userdata), Nla_data (Upcall_info->userdata));  if (upcall_info->egress_tun_info) {NLA = Nla_nest_start (USER_SKB, Ovs_packet_attr_egress_tun_key);
						    Upcall Information Object Add Egress_tun_info Err = Ovs_nla_put_egress_tunnel_key (USER_SKB, Upcall_info->egress_tun_info,
		upcall_info->egress_tun_opts);
		BUG_ON (ERR);
	Nla_nest_end (USER_SKB, NLA);  } if (Upcall_info->actions_len) {NLA = Nla_nest_start (USER_SKB, ovs_packet_attr_actions); Upcall Information Object Add actions Err = ovs_nla_put_actions (upcall_info->actions, Upcall_info->actions_len, user
		_SKB);
		if (!err) nla_nest_end (USER_SKB, NLA);
	else Nla_nest_cancel (USER_SKB, NLA); }/* ADD Ovs_packet_attr_mru */if (Upcall_info->mru) {if (Nla_put_u16 (USER_SKB, Ovs_packet_attr_mru, Upcall_
			Info->mru)) {err =-enobufs;
		Goto out;
	} pad_packet (DP, USER_SKB); }/* Only reserve the attribute header, packet data is added * in Skb_zerocopY () */if (! (
		NLA = Nla_reserve (USER_SKB, Ovs_packet_attr_packet, 0))) {err =-enobufs;
	Goto out;

	} Nla->nla_len = Nla_attr_size (Skb->len);    Err = Skb_zerocopy (USER_SKB, SKB, Skb->len, Hlen);

	Upcall Information Object Add message if (err) goto out;

	/* Pad Ovs_packet_attr_packet If linear copy was performed */Pad_packet (DP, USER_SKB);

	(struct NLMSGHDR *) user_skb->data)->nlmsg_len = user_skb->len;    Err = Genlmsg_unicast (Ovs_dp_get_net (DP), USER_SKB, Upcall_info->portid);
Send NetLink message user_skb = NULL;
	Out:if (Err) skb_tx_error (SKB);
	KFREE_SKB (USER_SKB);
	KFREE_SKB (NSKB);
return err;
 }

By this we can see that the userspace action and the exact flow table mismatch cause the Upcall to be more consistent in the process, both by invoking the Ovs_dp_upcall function to send the information to the user-state program. The Upcall processing thread is not dealt with in this analysis and will be given later in the analysis.

What functions can be achieved through userspace. Now I can not think of, and so on analysis Upcall processing, and then back to answer this question.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.