diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 259be67644e3..21448fa5d2e5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1352,6 +1352,10 @@ struct net_device_ops {
 						     struct ifla_vf_info *ivf);
 	int			(*ndo_set_vf_link_state)(struct net_device *dev,
 							 int vf, int link_state);
+	int                     (*ndo_set_vf_mirror)(struct net_device *dev,
+						     struct nlattr *vf_mirror);
+	int                     (*ndo_get_vf_mirror)(struct net_device *dev,
+						     struct ifla_vf_mirror_info *vf_mirror);
 	int			(*ndo_get_vf_stats)(struct net_device *dev,
 						    int vf,
 						    struct ifla_vf_stats
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 82708c6db432..b5cb3987e182 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -904,6 +904,7 @@ enum {
 	IFLA_VF_IB_PORT_GUID,	/* VF Infiniband port GUID */
 	IFLA_VF_VLAN_LIST,	/* nested list of vlans, option for QinQ */
 	IFLA_VF_BROADCAST,	/* VF broadcast */
+	IFLA_VF_MIRROR,
 	__IFLA_VF_MAX,
 };
 
@@ -998,6 +999,51 @@ struct ifla_vf_trust {
 	__u32 setting;
 };
 
+
+enum mirror_type {
+	IFLA_VF_MIRROR_CLEAR,
+	IFLA_VF_MIRROR_PF,
+	IFLA_VF_MIRROR_VF,
+	IFLA_VF_MIRROR_VLAN,
+	IFLA_VF_MIRROR_MAX,
+};
+
+#define PORT_MIRRORING_INGRESS (1U)
+#define PORT_MIRRORING_EGRESS (1U << 1)
+
+struct ifla_vf_mirror_vf {
+	__u32 dst_vf;
+	__u32 src_vf;
+	__u8 dir_mask;
+};
+
+struct ifla_vf_mirror_pf {
+	__u32 dst_vf;
+	__u8 dir_mask;
+};
+
+
+struct ifla_vf_mirror_vlan {
+	__u32 dst_vf;
+	__u32 vlan;
+};
+
+struct ifla_vf_mirror_clear {
+	__u32 dst_vf;
+};
+
+struct ifla_vf_mirror_info {
+	enum mirror_type action;
+	__u32 ele_index;
+	union {
+		__u32 dst_vf;
+		struct ifla_vf_mirror_vf vf_to_vf;
+		struct ifla_vf_mirror_pf pf_to_vf;
+		struct ifla_vf_mirror_vlan vlan_mirror;
+	};
+};
+
+
 /* VF ports management section
  *
  *	Nested layout of set/get msg is:
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 3d6ab194d0f5..a385e004bb9c 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -911,6 +911,117 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
 	a->rx_nohandler = b->rx_nohandler;
 }
 
+static int rtnl_put_vf_mirror_info(struct sk_buff *skb,
+				   struct ifla_vf_mirror_info *vf_mirror)
+{
+	switch (vf_mirror->action) {
+	case IFLA_VF_MIRROR_VF:
+		if (nla_put(skb, IFLA_VF_MIRROR_VF,
+			    sizeof(struct ifla_vf_mirror_vf),
+			    &vf_mirror->vf_to_vf) < 0)
+			return -EMSGSIZE;
+		break;
+	case IFLA_VF_MIRROR_PF:
+		if (nla_put(skb, IFLA_VF_MIRROR_PF,
+			    sizeof(struct ifla_vf_mirror_pf),
+			    &vf_mirror->pf_to_vf) < 0)
+			return -EMSGSIZE;
+		break;
+	case IFLA_VF_MIRROR_VLAN:
+		if (nla_put(skb, IFLA_VF_MIRROR_VLAN,
+			    sizeof(struct ifla_vf_mirror_vlan),
+			    &vf_mirror->vlan_mirror) < 0)
+			return -EMSGSIZE;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int rtnl_vf_mirror_fill(struct sk_buff *skb,
+			       struct net_device *dev,
+			       int vfid)
+{
+	struct ifla_vf_mirror_info vf_mirror;
+	int mirror_index = 0, err;
+	struct nlattr *vf_mirror_info;
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	if (!ops->ndo_get_vf_mirror)
+		return 0;
+	vf_mirror_info = nla_nest_start_noflag(skb, IFLA_VF_MIRROR);
+	if (!vf_mirror_info)
+		return -EMSGSIZE;
+
+	vf_mirror.dst_vf = vfid;
+	do {
+		vf_mirror.ele_index = mirror_index;
+		err = ops->ndo_get_vf_mirror(dev, &vf_mirror);
+		if (err == 0) {
+			err = rtnl_put_vf_mirror_info(skb, &vf_mirror);
+			mirror_index++;
+		}
+		if (err == -EAGAIN) {
+			err = 0;
+			mirror_index = 0;
+			nla_nest_cancel(skb, vf_mirror_info);
+			vf_mirror_info = nla_nest_start_noflag(skb,
+							       IFLA_VF_MIRROR);
+			if (!vf_mirror_info)
+				return -EMSGSIZE;
+		}
+	} while (err == 0);
+
+	if (err != -ENODATA) {
+		nla_nest_cancel(skb, vf_mirror_info);
+		return err;
+	}
+
+	nla_nest_end(skb, vf_mirror_info);
+	return 0;
+}
+
+static inline int rtnl_vf_mirror_info_size(struct net_device *dev)
+{
+	int vfid, mirror_index, nb_mirrors = 0;
+	int mirror_info_size;
+	struct ifla_vf_mirror_info vf_mirror;
+	int num_vfs;
+	int err;
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	if (!ops->ndo_get_vf_mirror)
+		return 0;
+
+	num_vfs = dev_num_vf(dev->dev.parent);
+	for (vfid = 0; vfid < num_vfs; vfid++) {
+		mirror_index = 0;
+		vf_mirror.dst_vf = vfid;
+		do {
+			vf_mirror.ele_index = mirror_index;
+			err = ops->ndo_get_vf_mirror(dev, &vf_mirror);
+			if (err == 0)
+				mirror_index++;
+		} while (err == 0);
+		if (err == -EAGAIN) {
+			vfid = -1;
+			nb_mirrors = 0;
+		} else if (err == -ENODATA) {
+			nb_mirrors += mirror_index;
+		} else {
+			return 0;
+		}
+	}
+
+	/* nest IFLA_VF_MIRROR for each VF*/
+	mirror_info_size = num_vfs * nla_total_size(0);
+
+	mirror_info_size += nb_mirrors *
+			    nla_total_size(sizeof(struct ifla_vf_mirror_vf));
+	return mirror_info_size;
+}
+
 /* All VF info */
 static inline int rtnl_vfinfo_size(const struct net_device *dev,
 				   u32 ext_filter_mask)
@@ -948,7 +1059,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev,
 			 nla_total_size_64bit(sizeof(__u64)) +
 			 /* IFLA_VF_STATS_TX_DROPPED */
 			 nla_total_size_64bit(sizeof(__u64)) +
-			 nla_total_size(sizeof(struct ifla_vf_trust)));
+			 nla_total_size(sizeof(struct ifla_vf_trust)) +
+			 rtnl_vf_mirror_info_size((struct net_device *)dev));
 		return size;
 	} else
 		return 0;
@@ -1356,6 +1468,8 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb,
 		goto nla_put_vf_failure;
 	}
 	nla_nest_end(skb, vfstats);
+	if (rtnl_vf_mirror_fill(skb, dev, vfs_num))
+		goto nla_put_vf_failure;
 	nla_nest_end(skb, vf);
 	return 0;
 
@@ -2487,6 +2601,13 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
 		return handle_vf_guid(dev, ivt, IFLA_VF_IB_PORT_GUID);
 	}
 
+	if (tb[IFLA_VF_MIRROR]) {
+		err = -EOPNOTSUPP;
+		if (ops->ndo_set_vf_mirror)
+			err = ops->ndo_set_vf_mirror(dev, tb[IFLA_VF_MIRROR]);
+		if (err < 0)
+			return err;
+	}
 	return err;
 }
 
