diff mbox

[v3] vxlan: Allow setting destination to unicast address.

Message ID 87hajcm7ym.wl%atzm@stratosphere.co.jp
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Atzm Watanabe April 12, 2013, 9:09 a.m. UTC
This patch allows setting VXLAN destination to unicast address.
It allows that VXLAN can be used as peer-to-peer tunnel without
multicast.

v3: move a new attribute REMOTE into the last of an enum list
    based by Stephen Hemminger's comments.

v2: use a new attribute REMOTE instead of GROUP based by
    Cong Wang's comments.

Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
---
 drivers/net/vxlan.c          | 45 ++++++++++++++++++++++++++++++++++----------
 include/uapi/linux/if_link.h |  1 +
 2 files changed, 36 insertions(+), 10 deletions(-)

Comments

David Miller April 15, 2013, 7:49 p.m. UTC | #1
From: Atzm Watanabe <atzm@stratosphere.co.jp>
Date: Fri, 12 Apr 2013 18:09:05 +0900

> This patch allows setting VXLAN destination to unicast address.
> It allows that VXLAN can be used as peer-to-peer tunnel without
> multicast.
> 
> v3: move a new attribute REMOTE into the last of an enum list
>     based by Stephen Hemminger's comments.
> 
> v2: use a new attribute REMOTE instead of GROUP based by
>     Cong Wang's comments.
> 
> Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>

Can someone familiar with the semantics and goals of vxlan please
review this patch?

Thanks.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Stevens April 15, 2013, 8:53 p.m. UTC | #2
netdev-owner@vger.kernel.org wrote on 04/12/2013 05:09:05 AM:

> From: Atzm Watanabe <atzm@stratosphere.co.jp>

> Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
> ---
>  drivers/net/vxlan.c          | 45 +++++++++++++++++++++++++++++++++
> +----------
>  include/uapi/linux/if_link.h |  1 +
>  2 files changed, 36 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> index 9a64715..e468d5a 100644
> --- a/drivers/net/vxlan.c
> +++ b/drivers/net/vxlan.c
> @@ -106,7 +106,7 @@ struct vxlan_dev {
>     struct hlist_node hlist;
>     struct net_device *dev;
>     __u32        vni;      /* virtual network id */
> -   __be32             gaddr;   /* multicast group */
> +   __be32             daddr;   /* destination address */
>     __be32        saddr;   /* source address */
>     unsigned int      link;      /* link to multicast over */
>     __u16        port_min;   /* source port range */

        This is effectively a default forwarding destination when
there is no matching fdb entry. As such, I think a fully general
patch would convert this to a "vxlan_rdst" and thereby allow alternate
port, vni, specific outgoing interface and multiple remote destinations
for copies, as via the fdb. And, in the future, support for this being
an IPv6 destination, as well. I think the name here, "daddr", ought to
reflect some of this too -- maybe "default_dst" or some such?


> @@ -1322,6 +1322,7 @@ static const struct nla_policy vxlan_policy
> [IFLA_VXLAN_MAX + 1] = {
>     [IFLA_VXLAN_RSC]   = { .type = NLA_U8 },
>     [IFLA_VXLAN_L2MISS]   = { .type = NLA_U8 },
>     [IFLA_VXLAN_L3MISS]   = { .type = NLA_U8 },
> +   [IFLA_VXLAN_REMOTE]   = { .len = FIELD_SIZEOF(struct iphdr, daddr) 
},
>  };
> 
>  static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])

I like the name change from "GROUP". "REMOTE" is ok, but might consider
"IFLA_VXLAN_DEFAULT_DST" or some such.

> @@ -1347,6 +1348,9 @@ static int vxlan_validate(struct nlattr *tb[],
> struct nlattr *data[])
>           return -ERANGE;
>     }
> 
> +   if (data[IFLA_VXLAN_GROUP] && data[IFLA_VXLAN_REMOTE])
> +      return -EINVAL;
> +
>     if (data[IFLA_VXLAN_GROUP]) {
>        __be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
>        if (!IN_MULTICAST(ntohl(gaddr))) {
> @@ -1355,6 +1359,14 @@ static int vxlan_validate(struct nlattr *tb
> [], struct nlattr *data[])
>        }
>     }
> 
> +   if (data[IFLA_VXLAN_REMOTE]) {
> +      __be32 daddr = nla_get_be32(data[IFLA_VXLAN_REMOTE]);
> +      if (IN_MULTICAST(ntohl(daddr))) {
> +         pr_debug("remote address is not IPv4 unicast\n");
> +         return -EADDRNOTAVAIL;
> +      }
> +   }
> +
>     if (data[IFLA_VXLAN_PORT_RANGE]) {
>        const struct ifla_vxlan_port_range *p
>           = nla_data(data[IFLA_VXLAN_PORT_RANGE]);

If this is turned into a vxlan_rdst, it should check for other
attributes to fill that-- PORT, VNI, IFINDEX-- with approprate
default values if not present.

Overall, this patch looks ok to me as far as it goes, but I think
it'd be more useful if it were more generic; that is, if it supported
everything an fdb can.

                                                        +-DLS

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mike Rapoport April 16, 2013, 6:46 a.m. UTC | #3
On Mon, Apr 15, 2013 at 11:53 PM, David Stevens <dlstevens@us.ibm.com> wrote:
> netdev-owner@vger.kernel.org wrote on 04/12/2013 05:09:05 AM:
>
>> From: Atzm Watanabe <atzm@stratosphere.co.jp>
>
>> Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
>> ---
>
> If this is turned into a vxlan_rdst, it should check for other
> attributes to fill that-- PORT, VNI, IFINDEX-- with approprate
> default values if not present.
>
> Overall, this patch looks ok to me as far as it goes, but I think
> it'd be more useful if it were more generic; that is, if it supported
> everything an fdb can.

I've just sent an rfc patch that is slightly more generic version of
Atzm Watanabe work (1). It makes the "default destination" a list of
destinations rather than a single entry.
If the approach seems Ok, I can extend it to do "everything an fdb can".


(1) http://thread.gmane.org/gmane.linux.network/265871

>                                                         +-DLS
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Atzm Watanabe April 16, 2013, 12:50 p.m. UTC | #4
At Mon, 15 Apr 2013 16:53:35 -0400,
David Stevens wrote:
> 
> netdev-owner@vger.kernel.org wrote on 04/12/2013 05:09:05 AM:
> 
> > From: Atzm Watanabe <atzm@stratosphere.co.jp>
> 
> > Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
> > ---
> >  drivers/net/vxlan.c          | 45 +++++++++++++++++++++++++++++++++
> > +----------
> >  include/uapi/linux/if_link.h |  1 +
> >  2 files changed, 36 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> > index 9a64715..e468d5a 100644
> > --- a/drivers/net/vxlan.c
> > +++ b/drivers/net/vxlan.c
> > @@ -106,7 +106,7 @@ struct vxlan_dev {
> >     struct hlist_node hlist;
> >     struct net_device *dev;
> >     __u32        vni;      /* virtual network id */
> > -   __be32             gaddr;   /* multicast group */
> > +   __be32             daddr;   /* destination address */
> >     __be32        saddr;   /* source address */
> >     unsigned int      link;      /* link to multicast over */
> >     __u16        port_min;   /* source port range */
> 
>         This is effectively a default forwarding destination when
> there is no matching fdb entry. As such, I think a fully general
> patch would convert this to a "vxlan_rdst" and thereby allow alternate
> port, vni, specific outgoing interface and multiple remote destinations
> for copies, as via the fdb. And, in the future, support for this being
> an IPv6 destination, as well. I think the name here, "daddr", ought to
> reflect some of this too -- maybe "default_dst" or some such?

Yes, right.  I'll replace "gaddr" with "default_dst" as vxlan_rdst.

But to support multiple default destinations, it will need more fixes
like Mike Rapoport's patch.  Also it will need careful consideration
about VNI...  I'll try to fix them to support multiple default
destinations, after the patch is merged.


> > @@ -1322,6 +1322,7 @@ static const struct nla_policy vxlan_policy
> > [IFLA_VXLAN_MAX + 1] = {
> >     [IFLA_VXLAN_RSC]   = { .type = NLA_U8 },
> >     [IFLA_VXLAN_L2MISS]   = { .type = NLA_U8 },
> >     [IFLA_VXLAN_L3MISS]   = { .type = NLA_U8 },
> > +   [IFLA_VXLAN_REMOTE]   = { .len = FIELD_SIZEOF(struct iphdr, daddr) 
> },
> >  };
> > 
> >  static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
> 
> I like the name change from "GROUP". "REMOTE" is ok, but might consider
> "IFLA_VXLAN_DEFAULT_DST" or some such.

Hmm...  I think that "IFLA_VXLAN_DEFAULT_DST" might be confused with
vxlan_rdst.  So I'll just replace "GROUP" with "REMOTE".

But in the future, to support multiple default destinations,
"DEFAULT_DST" attribute might be used to add a destination entry :)


> > @@ -1347,6 +1348,9 @@ static int vxlan_validate(struct nlattr *tb[],
> > struct nlattr *data[])
> >           return -ERANGE;
> >     }
> > 
> > +   if (data[IFLA_VXLAN_GROUP] && data[IFLA_VXLAN_REMOTE])
> > +      return -EINVAL;
> > +
> >     if (data[IFLA_VXLAN_GROUP]) {
> >        __be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
> >        if (!IN_MULTICAST(ntohl(gaddr))) {
> > @@ -1355,6 +1359,14 @@ static int vxlan_validate(struct nlattr *tb
> > [], struct nlattr *data[])
> >        }
> >     }
> > 
> > +   if (data[IFLA_VXLAN_REMOTE]) {
> > +      __be32 daddr = nla_get_be32(data[IFLA_VXLAN_REMOTE]);
> > +      if (IN_MULTICAST(ntohl(daddr))) {
> > +         pr_debug("remote address is not IPv4 unicast\n");
> > +         return -EADDRNOTAVAIL;
> > +      }
> > +   }
> > +
> >     if (data[IFLA_VXLAN_PORT_RANGE]) {
> >        const struct ifla_vxlan_port_range *p
> >           = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
> 
> If this is turned into a vxlan_rdst, it should check for other
> attributes to fill that-- PORT, VNI, IFINDEX-- with approprate
> default values if not present.
> 
> Overall, this patch looks ok to me as far as it goes, but I think
> it'd be more useful if it were more generic; that is, if it supported
> everything an fdb can.

Thank you for the reviewing!
I'll fix that mentioned above and resend patches.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Atzm Watanabe April 16, 2013, 12:50 p.m. UTC | #5
At Tue, 16 Apr 2013 09:46:36 +0300,
Mike Rapoport wrote:
> 
> On Mon, Apr 15, 2013 at 11:53 PM, David Stevens <dlstevens@us.ibm.com> wrote:
> > netdev-owner@vger.kernel.org wrote on 04/12/2013 05:09:05 AM:
> >
> >> From: Atzm Watanabe <atzm@stratosphere.co.jp>
> >
> >> Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
> >> ---
> >
> > If this is turned into a vxlan_rdst, it should check for other
> > attributes to fill that-- PORT, VNI, IFINDEX-- with approprate
> > default values if not present.
> >
> > Overall, this patch looks ok to me as far as it goes, but I think
> > it'd be more useful if it were more generic; that is, if it supported
> > everything an fdb can.
> 
> I've just sent an rfc patch that is slightly more generic version of
> Atzm Watanabe work (1). It makes the "default destination" a list of
> destinations rather than a single entry.
> If the approach seems Ok, I can extend it to do "everything an fdb can".
> 
> 
> (1) http://thread.gmane.org/gmane.linux.network/265871

For more generalization, I think that "group_head" should replace
"gaddr" and related struct members, and "group_head" should allow
multicast addresses, and then multicast join/leave should be done.

I've trying to replace "gaddr" with "defaut destination" as vxlan_rdst
(but it can be set single destination yet).
I'll send the patch soon.  Could you review it?

Thanks.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Stevens April 16, 2013, 1:04 p.m. UTC | #6
netdev-owner@vger.kernel.org wrote on 04/16/2013 02:46:36 AM:

> From: Mike Rapoport <mike.rapoport@ravellosystems.com>

> I've just sent an rfc patch that is slightly more generic version of
> Atzm Watanabe work (1). It makes the "default destination" a list of
> destinations rather than a single entry.
> If the approach seems Ok, I can extend it to do "everything an fdb can".

I'd like to see those combined, with the "group" references changed to
"remote_default", "default_dst" or something along those lines to
indicate it is a default fdb entry.

When a new list element is a multicast address, also join the group
for receive side.

Also allow PORT, VNI and IFINDEX attributes, and require nonzero,
valid IFINDEX for multicast destinations.

So, yes, I think your patch is a step in the right direction.

                                                +-DLS

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mike Rapoport April 16, 2013, 2:22 p.m. UTC | #7
On Tue, Apr 16, 2013 at 3:50 PM, Atzm Watanabe <atzm@stratosphere.co.jp> wrote:
> At Mon, 15 Apr 2013 16:53:35 -0400,
> David Stevens wrote:
>>
>> netdev-owner@vger.kernel.org wrote on 04/12/2013 05:09:05 AM:
>>
>> > From: Atzm Watanabe <atzm@stratosphere.co.jp>
>>
>> > Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
>> > ---
>> >  drivers/net/vxlan.c          | 45 +++++++++++++++++++++++++++++++++
>> > +----------
>> >  include/uapi/linux/if_link.h |  1 +
>> >  2 files changed, 36 insertions(+), 10 deletions(-)
>> >
>> > diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
>> > index 9a64715..e468d5a 100644
>> > --- a/drivers/net/vxlan.c
>> > +++ b/drivers/net/vxlan.c
>> > @@ -106,7 +106,7 @@ struct vxlan_dev {
>> >     struct hlist_node hlist;
>> >     struct net_device *dev;
>> >     __u32        vni;      /* virtual network id */
>> > -   __be32             gaddr;   /* multicast group */
>> > +   __be32             daddr;   /* destination address */
>> >     __be32        saddr;   /* source address */
>> >     unsigned int      link;      /* link to multicast over */
>> >     __u16        port_min;   /* source port range */
>>
>>         This is effectively a default forwarding destination when
>> there is no matching fdb entry. As such, I think a fully general
>> patch would convert this to a "vxlan_rdst" and thereby allow alternate
>> port, vni, specific outgoing interface and multiple remote destinations
>> for copies, as via the fdb. And, in the future, support for this being
>> an IPv6 destination, as well. I think the name here, "daddr", ought to
>> reflect some of this too -- maybe "default_dst" or some such?
>
> Yes, right.  I'll replace "gaddr" with "default_dst" as vxlan_rdst.
>
> But to support multiple default destinations, it will need more fixes
> like Mike Rapoport's patch.  Also it will need careful consideration
> about VNI...  I'll try to fix them to support multiple default
> destinations, after the patch is merged.

I can add multiple destinations myself if you'd prefer it that way :)

>> > @@ -1322,6 +1322,7 @@ static const struct nla_policy vxlan_policy
>> > [IFLA_VXLAN_MAX + 1] = {
>> >     [IFLA_VXLAN_RSC]   = { .type = NLA_U8 },
>> >     [IFLA_VXLAN_L2MISS]   = { .type = NLA_U8 },
>> >     [IFLA_VXLAN_L3MISS]   = { .type = NLA_U8 },
>> > +   [IFLA_VXLAN_REMOTE]   = { .len = FIELD_SIZEOF(struct iphdr, daddr)
>> },
>> >  };
>> >
>> >  static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
>>
>> I like the name change from "GROUP". "REMOTE" is ok, but might consider
>> "IFLA_VXLAN_DEFAULT_DST" or some such.
>
> Hmm...  I think that "IFLA_VXLAN_DEFAULT_DST" might be confused with
> vxlan_rdst.  So I'll just replace "GROUP" with "REMOTE".
>
> But in the future, to support multiple default destinations,
> "DEFAULT_DST" attribute might be used to add a destination entry :)
>
>
>> > @@ -1347,6 +1348,9 @@ static int vxlan_validate(struct nlattr *tb[],
>> > struct nlattr *data[])
>> >           return -ERANGE;
>> >     }
>> >
>> > +   if (data[IFLA_VXLAN_GROUP] && data[IFLA_VXLAN_REMOTE])
>> > +      return -EINVAL;
>> > +
>> >     if (data[IFLA_VXLAN_GROUP]) {
>> >        __be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
>> >        if (!IN_MULTICAST(ntohl(gaddr))) {
>> > @@ -1355,6 +1359,14 @@ static int vxlan_validate(struct nlattr *tb
>> > [], struct nlattr *data[])
>> >        }
>> >     }
>> >
>> > +   if (data[IFLA_VXLAN_REMOTE]) {
>> > +      __be32 daddr = nla_get_be32(data[IFLA_VXLAN_REMOTE]);
>> > +      if (IN_MULTICAST(ntohl(daddr))) {
>> > +         pr_debug("remote address is not IPv4 unicast\n");
>> > +         return -EADDRNOTAVAIL;
>> > +      }
>> > +   }
>> > +
>> >     if (data[IFLA_VXLAN_PORT_RANGE]) {
>> >        const struct ifla_vxlan_port_range *p
>> >           = nla_data(data[IFLA_VXLAN_PORT_RANGE]);
>>
>> If this is turned into a vxlan_rdst, it should check for other
>> attributes to fill that-- PORT, VNI, IFINDEX-- with approprate
>> default values if not present.
>>
>> Overall, this patch looks ok to me as far as it goes, but I think
>> it'd be more useful if it were more generic; that is, if it supported
>> everything an fdb can.
>
> Thank you for the reviewing!
> I'll fix that mentioned above and resend patches.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Atzm Watanabe April 16, 2013, 5:48 p.m. UTC | #8
At Tue, 16 Apr 2013 17:22:14 +0300,
Mike Rapoport wrote:
> 
> On Tue, Apr 16, 2013 at 3:50 PM, Atzm Watanabe <atzm@stratosphere.co.jp> wrote:
> > At Mon, 15 Apr 2013 16:53:35 -0400,
> > David Stevens wrote:
> >>
> >> netdev-owner@vger.kernel.org wrote on 04/12/2013 05:09:05 AM:
> >>
> >> > From: Atzm Watanabe <atzm@stratosphere.co.jp>
> >>
> >> > Signed-off-by: Atzm Watanabe <atzm@stratosphere.co.jp>
> >> > ---
> >> >  drivers/net/vxlan.c          | 45 +++++++++++++++++++++++++++++++++
> >> > +----------
> >> >  include/uapi/linux/if_link.h |  1 +
> >> >  2 files changed, 36 insertions(+), 10 deletions(-)
> >> >
> >> > diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> >> > index 9a64715..e468d5a 100644
> >> > --- a/drivers/net/vxlan.c
> >> > +++ b/drivers/net/vxlan.c
> >> > @@ -106,7 +106,7 @@ struct vxlan_dev {
> >> >     struct hlist_node hlist;
> >> >     struct net_device *dev;
> >> >     __u32        vni;      /* virtual network id */
> >> > -   __be32             gaddr;   /* multicast group */
> >> > +   __be32             daddr;   /* destination address */
> >> >     __be32        saddr;   /* source address */
> >> >     unsigned int      link;      /* link to multicast over */
> >> >     __u16        port_min;   /* source port range */
> >>
> >>         This is effectively a default forwarding destination when
> >> there is no matching fdb entry. As such, I think a fully general
> >> patch would convert this to a "vxlan_rdst" and thereby allow alternate
> >> port, vni, specific outgoing interface and multiple remote destinations
> >> for copies, as via the fdb. And, in the future, support for this being
> >> an IPv6 destination, as well. I think the name here, "daddr", ought to
> >> reflect some of this too -- maybe "default_dst" or some such?
> >
> > Yes, right.  I'll replace "gaddr" with "default_dst" as vxlan_rdst.
> >
> > But to support multiple default destinations, it will need more fixes
> > like Mike Rapoport's patch.  Also it will need careful consideration
> > about VNI...  I'll try to fix them to support multiple default
> > destinations, after the patch is merged.
> 
> I can add multiple destinations myself if you'd prefer it that way :)

Great!

I think that supporting unicast address and supporting multiple
destinations are related (and similar on the code) but different
topics essentially.  So I'd appreciate it if you post the patch
(titled "support multiple default destinations" or some such) in
addition to my changes when it merged.

Thanks!
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 9a64715..e468d5a 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -106,7 +106,7 @@  struct vxlan_dev {
 	struct hlist_node hlist;
 	struct net_device *dev;
 	__u32		  vni;		/* virtual network id */
-	__be32	          gaddr;	/* multicast group */
+	__be32	          daddr;	/* destination address */
 	__be32		  saddr;	/* source address */
 	unsigned int      link;		/* link to multicast over */
 	__u16		  port_min;	/* source port range */
@@ -591,7 +591,7 @@  static bool vxlan_group_used(struct vxlan_net *vn,
 			if (!netif_running(vxlan->dev))
 				continue;
 
-			if (vxlan->gaddr == this->gaddr)
+			if (vxlan->daddr == this->daddr)
 				return true;
 		}
 
@@ -605,7 +605,7 @@  static int vxlan_join_group(struct net_device *dev)
 	struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
 	struct sock *sk = vn->sock->sk;
 	struct ip_mreqn mreq = {
-		.imr_multiaddr.s_addr	= vxlan->gaddr,
+		.imr_multiaddr.s_addr	= vxlan->daddr,
 		.imr_ifindex		= vxlan->link,
 	};
 	int err;
@@ -633,7 +633,7 @@  static int vxlan_leave_group(struct net_device *dev)
 	int err = 0;
 	struct sock *sk = vn->sock->sk;
 	struct ip_mreqn mreq = {
-		.imr_multiaddr.s_addr	= vxlan->gaddr,
+		.imr_multiaddr.s_addr	= vxlan->daddr,
 		.imr_ifindex		= vxlan->link,
 	};
 
@@ -1106,7 +1106,7 @@  static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 		did_rsc = false;
 		group.remote_port = vxlan_port;
 		group.remote_vni = vxlan->vni;
-		group.remote_ip = vxlan->gaddr;
+		group.remote_ip = vxlan->daddr;
 		group.remote_ifindex = vxlan->link;
 		group.remote_next = 0;
 		rdst0 = &group;
@@ -1189,7 +1189,7 @@  static int vxlan_open(struct net_device *dev)
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	int err;
 
-	if (vxlan->gaddr) {
+	if (IN_MULTICAST(ntohl(vxlan->daddr))) {
 		err = vxlan_join_group(dev);
 		if (err)
 			return err;
@@ -1223,7 +1223,7 @@  static int vxlan_stop(struct net_device *dev)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 
-	if (vxlan->gaddr)
+	if (IN_MULTICAST(ntohl(vxlan->daddr)))
 		vxlan_leave_group(dev);
 
 	del_timer_sync(&vxlan->age_timer);
@@ -1322,6 +1322,7 @@  static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
 	[IFLA_VXLAN_RSC]	= { .type = NLA_U8 },
 	[IFLA_VXLAN_L2MISS]	= { .type = NLA_U8 },
 	[IFLA_VXLAN_L3MISS]	= { .type = NLA_U8 },
+	[IFLA_VXLAN_REMOTE]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
 };
 
 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1347,6 +1348,9 @@  static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
 			return -ERANGE;
 	}
 
+	if (data[IFLA_VXLAN_GROUP] && data[IFLA_VXLAN_REMOTE])
+		return -EINVAL;
+
 	if (data[IFLA_VXLAN_GROUP]) {
 		__be32 gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
 		if (!IN_MULTICAST(ntohl(gaddr))) {
@@ -1355,6 +1359,14 @@  static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
 		}
 	}
 
+	if (data[IFLA_VXLAN_REMOTE]) {
+		__be32 daddr = nla_get_be32(data[IFLA_VXLAN_REMOTE]);
+		if (IN_MULTICAST(ntohl(daddr))) {
+			pr_debug("remote address is not IPv4 unicast\n");
+			return -EADDRNOTAVAIL;
+		}
+	}
+
 	if (data[IFLA_VXLAN_PORT_RANGE]) {
 		const struct ifla_vxlan_port_range *p
 			= nla_data(data[IFLA_VXLAN_PORT_RANGE]);
@@ -1399,7 +1411,10 @@  static int vxlan_newlink(struct net *net, struct net_device *dev,
 	vxlan->vni = vni;
 
 	if (data[IFLA_VXLAN_GROUP])
-		vxlan->gaddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
+		vxlan->daddr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
+
+	if (data[IFLA_VXLAN_REMOTE])
+		vxlan->daddr = nla_get_be32(data[IFLA_VXLAN_REMOTE]);
 
 	if (data[IFLA_VXLAN_LOCAL])
 		vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]);
@@ -1492,6 +1507,7 @@  static size_t vxlan_get_size(const struct net_device *dev)
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_L3MISS */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_AGEING */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_LIMIT */
+		nla_total_size(sizeof(__be32))+	/* IFLA_VXLAN_REMOTE */
 		nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
 		0;
 }
@@ -1507,8 +1523,17 @@  static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	if (nla_put_u32(skb, IFLA_VXLAN_ID, vxlan->vni))
 		goto nla_put_failure;
 
-	if (vxlan->gaddr && nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->gaddr))
-		goto nla_put_failure;
+	if (vxlan->daddr) {
+		int err;
+
+		if (IN_MULTICAST(ntohl(vxlan->daddr)))
+			err = nla_put_be32(skb, IFLA_VXLAN_GROUP, vxlan->daddr);
+		else
+			err = nla_put_be32(skb, IFLA_VXLAN_REMOTE, vxlan->daddr);
+
+		if (err)
+			goto nla_put_failure;
+	}
 
 	if (vxlan->link && nla_put_u32(skb, IFLA_VXLAN_LINK, vxlan->link))
 		goto nla_put_failure;
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6b35c42..afc8027 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -309,6 +309,7 @@  enum {
 	IFLA_VXLAN_RSC,
 	IFLA_VXLAN_L2MISS,
 	IFLA_VXLAN_L3MISS,
+	IFLA_VXLAN_REMOTE,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)