net/openvswitch/meter.c

Source file repositories/reference/linux-study-clean/net/openvswitch/meter.c

File Facts

System
Linux kernel
Corpus path
net/openvswitch/meter.c
Extension
.c
Size
18773 bytes
Lines
767
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source 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

dp_meter_instance_realloc(tbl, ti->n_meters * 2)) {
		err = -ENOMEM;
		goto attach_err;
	}

	return 0;

attach_err:
	dp_meter_instance_remove(ti, meter);
	tbl->count--;
	return err;
}

static int detach_meter(struct dp_meter_table *tbl, struct dp_meter *meter)
{
	struct dp_meter_instance *ti;

	ASSERT_OVSL();
	if (!meter)
		return 0;

	ti = rcu_dereference_ovsl(tbl->ti);
	dp_meter_instance_remove(ti, meter);

	tbl->count--;

	/* Shrink the meter array if necessary. */
	if (ti->n_meters > DP_METER_ARRAY_SIZE_MIN &&
	    tbl->count <= (ti->n_meters / 4)) {
		int half_size = ti->n_meters / 2;
		int i;

		/* Avoid hash collision, don't move slots to other place.
		 * Make sure there are no references of meters in array
		 * which will be released.
		 */
		for (i = half_size; i < ti->n_meters; i++)
			if (rcu_dereference_ovsl(ti->dp_meters[i]))
				goto out;

		if (dp_meter_instance_realloc(tbl, half_size))
			goto shrink_err;
	}

out:
	return 0;

shrink_err:
	dp_meter_instance_insert(ti, meter);
	tbl->count++;
	return -ENOMEM;
}

static struct sk_buff *
ovs_meter_cmd_reply_start(struct genl_info *info, u8 cmd,
			  struct ovs_header **ovs_reply_header)
{
	struct sk_buff *skb;
	struct ovs_header *ovs_header = genl_info_userhdr(info);

	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
	if (!skb)
		return ERR_PTR(-ENOMEM);

	*ovs_reply_header = genlmsg_put(skb, info->snd_portid,
					info->snd_seq,
					&dp_meter_genl_family, 0, cmd);
	if (!*ovs_reply_header) {
		nlmsg_free(skb);
		return ERR_PTR(-EMSGSIZE);
	}
	(*ovs_reply_header)->dp_ifindex = ovs_header->dp_ifindex;

	return skb;
}

static int ovs_meter_cmd_reply_stats(struct sk_buff *reply, u32 meter_id,
				     struct dp_meter *meter)
{
	struct nlattr *nla;
	struct dp_meter_band *band;
	u16 i;

	if (nla_put_u32(reply, OVS_METER_ATTR_ID, meter_id))
		goto error;

	if (nla_put(reply, OVS_METER_ATTR_STATS,
		    sizeof(struct ovs_flow_stats), &meter->stats))
		goto error;

Annotation

Implementation Notes