linux/include/net/vxlan.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef __NET_VXLAN_H
   3#define __NET_VXLAN_H 1
   4
   5#include <linux/if_vlan.h>
   6#include <net/udp_tunnel.h>
   7#include <net/dst_metadata.h>
   8#include <net/rtnetlink.h>
   9#include <net/switchdev.h>
  10#include <net/nexthop.h>
  11
  12#define IANA_VXLAN_UDP_PORT     4789
  13#define IANA_VXLAN_GPE_UDP_PORT 4790
  14
  15/* VXLAN protocol (RFC 7348) header:
  16 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  17 * |R|R|R|R|I|R|R|R|               Reserved                        |
  18 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  19 * |                VXLAN Network Identifier (VNI) |   Reserved    |
  20 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  21 *
  22 * I = VXLAN Network Identifier (VNI) present.
  23 */
  24struct vxlanhdr {
  25        __be32 vx_flags;
  26        __be32 vx_vni;
  27};
  28
  29/* VXLAN header flags. */
  30#define VXLAN_HF_VNI    cpu_to_be32(BIT(27))
  31
  32#define VXLAN_N_VID     (1u << 24)
  33#define VXLAN_VID_MASK  (VXLAN_N_VID - 1)
  34#define VXLAN_VNI_MASK  cpu_to_be32(VXLAN_VID_MASK << 8)
  35#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr))
  36
  37#define VNI_HASH_BITS   10
  38#define VNI_HASH_SIZE   (1<<VNI_HASH_BITS)
  39#define FDB_HASH_BITS   8
  40#define FDB_HASH_SIZE   (1<<FDB_HASH_BITS)
  41
  42/* Remote checksum offload for VXLAN (VXLAN_F_REMCSUM_[RT]X):
  43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  44 * |R|R|R|R|I|R|R|R|R|R|C|              Reserved                   |
  45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  46 * |           VXLAN Network Identifier (VNI)      |O| Csum start  |
  47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  48 *
  49 * C = Remote checksum offload bit. When set indicates that the
  50 *     remote checksum offload data is present.
  51 *
  52 * O = Offset bit. Indicates the checksum offset relative to
  53 *     checksum start.
  54 *
  55 * Csum start = Checksum start divided by two.
  56 *
  57 * http://tools.ietf.org/html/draft-herbert-vxlan-rco
  58 */
  59
  60/* VXLAN-RCO header flags. */
  61#define VXLAN_HF_RCO    cpu_to_be32(BIT(21))
  62
  63/* Remote checksum offload header option */
  64#define VXLAN_RCO_MASK  cpu_to_be32(0x7f)  /* Last byte of vni field */
  65#define VXLAN_RCO_UDP   cpu_to_be32(0x80)  /* Indicate UDP RCO (TCP when not set *) */
  66#define VXLAN_RCO_SHIFT 1                  /* Left shift of start */
  67#define VXLAN_RCO_SHIFT_MASK ((1 << VXLAN_RCO_SHIFT) - 1)
  68#define VXLAN_MAX_REMCSUM_START (0x7f << VXLAN_RCO_SHIFT)
  69
  70/*
  71 * VXLAN Group Based Policy Extension (VXLAN_F_GBP):
  72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  73 * |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
  74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  75 * |                VXLAN Network Identifier (VNI) |   Reserved    |
  76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  77 *
  78 * G = Group Policy ID present.
  79 *
  80 * D = Don't Learn bit. When set, this bit indicates that the egress
  81 *     VTEP MUST NOT learn the source address of the encapsulated frame.
  82 *
  83 * A = Indicates that the group policy has already been applied to
  84 *     this packet. Policies MUST NOT be applied by devices when the
  85 *     A bit is set.
  86 *
  87 * https://tools.ietf.org/html/draft-smith-vxlan-group-policy
  88 */
  89struct vxlanhdr_gbp {
  90        u8      vx_flags;
  91#ifdef __LITTLE_ENDIAN_BITFIELD
  92        u8      reserved_flags1:3,
  93                policy_applied:1,
  94                reserved_flags2:2,
  95                dont_learn:1,
  96                reserved_flags3:1;
  97#elif defined(__BIG_ENDIAN_BITFIELD)
  98        u8      reserved_flags1:1,
  99                dont_learn:1,
 100                reserved_flags2:2,
 101                policy_applied:1,
 102                reserved_flags3:3;
 103#else
 104#error  "Please fix <asm/byteorder.h>"
 105#endif
 106        __be16  policy_id;
 107        __be32  vx_vni;
 108};
 109
 110/* VXLAN-GBP header flags. */
 111#define VXLAN_HF_GBP    cpu_to_be32(BIT(31))
 112
 113#define VXLAN_GBP_USED_BITS (VXLAN_HF_GBP | cpu_to_be32(0xFFFFFF))
 114
 115/* skb->mark mapping
 116 *
 117 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 118 * |R|R|R|R|R|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
 119 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 120 */
 121#define VXLAN_GBP_DONT_LEARN            (BIT(6) << 16)
 122#define VXLAN_GBP_POLICY_APPLIED        (BIT(3) << 16)
 123#define VXLAN_GBP_ID_MASK               (0xFFFF)
 124
 125#define VXLAN_GBP_MASK (VXLAN_GBP_DONT_LEARN | VXLAN_GBP_POLICY_APPLIED | \
 126                        VXLAN_GBP_ID_MASK)
 127
 128/*
 129 * VXLAN Generic Protocol Extension (VXLAN_F_GPE):
 130 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 131 * |R|R|Ver|I|P|R|O|       Reserved                |Next Protocol  |
 132 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 133 * |                VXLAN Network Identifier (VNI) |   Reserved    |
 134 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 135 *
 136 * Ver = Version. Indicates VXLAN GPE protocol version.
 137 *
 138 * P = Next Protocol Bit. The P bit is set to indicate that the
 139 *     Next Protocol field is present.
 140 *
 141 * O = OAM Flag Bit. The O bit is set to indicate that the packet
 142 *     is an OAM packet.
 143 *
 144 * Next Protocol = This 8 bit field indicates the protocol header
 145 * immediately following the VXLAN GPE header.
 146 *
 147 * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01
 148 */
 149
 150struct vxlanhdr_gpe {
 151#if defined(__LITTLE_ENDIAN_BITFIELD)
 152        u8      oam_flag:1,
 153                reserved_flags1:1,
 154                np_applied:1,
 155                instance_applied:1,
 156                version:2,
 157                reserved_flags2:2;
 158#elif defined(__BIG_ENDIAN_BITFIELD)
 159        u8      reserved_flags2:2,
 160                version:2,
 161                instance_applied:1,
 162                np_applied:1,
 163                reserved_flags1:1,
 164                oam_flag:1;
 165#endif
 166        u8      reserved_flags3;
 167        u8      reserved_flags4;
 168        u8      next_protocol;
 169        __be32  vx_vni;
 170};
 171
 172/* VXLAN-GPE header flags. */
 173#define VXLAN_HF_VER    cpu_to_be32(BIT(29) | BIT(28))
 174#define VXLAN_HF_NP     cpu_to_be32(BIT(26))
 175#define VXLAN_HF_OAM    cpu_to_be32(BIT(24))
 176
 177#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \
 178                             cpu_to_be32(0xff))
 179
 180struct vxlan_metadata {
 181        u32             gbp;
 182};
 183
 184/* per UDP socket information */
 185struct vxlan_sock {
 186        struct hlist_node hlist;
 187        struct socket    *sock;
 188        struct hlist_head vni_list[VNI_HASH_SIZE];
 189        refcount_t        refcnt;
 190        u32               flags;
 191};
 192
 193union vxlan_addr {
 194        struct sockaddr_in sin;
 195        struct sockaddr_in6 sin6;
 196        struct sockaddr sa;
 197};
 198
 199struct vxlan_rdst {
 200        union vxlan_addr         remote_ip;
 201        __be16                   remote_port;
 202        u8                       offloaded:1;
 203        __be32                   remote_vni;
 204        u32                      remote_ifindex;
 205        struct net_device        *remote_dev;
 206        struct list_head         list;
 207        struct rcu_head          rcu;
 208        struct dst_cache         dst_cache;
 209};
 210
 211struct vxlan_config {
 212        union vxlan_addr        remote_ip;
 213        union vxlan_addr        saddr;
 214        __be32                  vni;
 215        int                     remote_ifindex;
 216        int                     mtu;
 217        __be16                  dst_port;
 218        u16                     port_min;
 219        u16                     port_max;
 220        u8                      tos;
 221        u8                      ttl;
 222        __be32                  label;
 223        u32                     flags;
 224        unsigned long           age_interval;
 225        unsigned int            addrmax;
 226        bool                    no_share;
 227        enum ifla_vxlan_df      df;
 228};
 229
 230enum {
 231        VXLAN_VNI_STATS_RX,
 232        VXLAN_VNI_STATS_RX_DROPS,
 233        VXLAN_VNI_STATS_RX_ERRORS,
 234        VXLAN_VNI_STATS_TX,
 235        VXLAN_VNI_STATS_TX_DROPS,
 236        VXLAN_VNI_STATS_TX_ERRORS,
 237};
 238
 239struct vxlan_vni_stats {
 240        u64 rx_packets;
 241        u64 rx_bytes;
 242        u64 rx_drops;
 243        u64 rx_errors;
 244        u64 tx_packets;
 245        u64 tx_bytes;
 246        u64 tx_drops;
 247        u64 tx_errors;
 248};
 249
 250struct vxlan_vni_stats_pcpu {
 251        struct vxlan_vni_stats stats;
 252        struct u64_stats_sync syncp;
 253};
 254
 255struct vxlan_dev_node {
 256        struct hlist_node hlist;
 257        struct vxlan_dev *vxlan;
 258};
 259
 260struct vxlan_vni_node {
 261        struct rhash_head vnode;
 262        struct vxlan_dev_node hlist4; /* vni hash table for IPv4 socket */
 263#if IS_ENABLED(CONFIG_IPV6)
 264        struct vxlan_dev_node hlist6; /* vni hash table for IPv6 socket */
 265#endif
 266        struct list_head vlist;
 267        __be32 vni;
 268        union vxlan_addr remote_ip; /* default remote ip for this vni */
 269        struct vxlan_vni_stats_pcpu __percpu *stats;
 270
 271        struct rcu_head rcu;
 272};
 273
 274struct vxlan_vni_group {
 275        struct rhashtable       vni_hash;
 276        struct list_head        vni_list;
 277        u32                     num_vnis;
 278};
 279
 280/* Pseudo network device */
 281struct vxlan_dev {
 282        struct vxlan_dev_node hlist4;   /* vni hash table for IPv4 socket */
 283#if IS_ENABLED(CONFIG_IPV6)
 284        struct vxlan_dev_node hlist6;   /* vni hash table for IPv6 socket */
 285#endif
 286        struct list_head  next;         /* vxlan's per namespace list */
 287        struct vxlan_sock __rcu *vn4_sock;      /* listening socket for IPv4 */
 288#if IS_ENABLED(CONFIG_IPV6)
 289        struct vxlan_sock __rcu *vn6_sock;      /* listening socket for IPv6 */
 290#endif
 291        struct net_device *dev;
 292        struct net        *net;         /* netns for packet i/o */
 293        struct vxlan_rdst default_dst;  /* default destination */
 294
 295        struct timer_list age_timer;
 296        spinlock_t        hash_lock[FDB_HASH_SIZE];
 297        unsigned int      addrcnt;
 298        struct gro_cells  gro_cells;
 299
 300        struct vxlan_config     cfg;
 301
 302        struct vxlan_vni_group  __rcu *vnigrp;
 303
 304        struct hlist_head fdb_head[FDB_HASH_SIZE];
 305};
 306
 307#define VXLAN_F_LEARN                   0x01
 308#define VXLAN_F_PROXY                   0x02
 309#define VXLAN_F_RSC                     0x04
 310#define VXLAN_F_L2MISS                  0x08
 311#define VXLAN_F_L3MISS                  0x10
 312#define VXLAN_F_IPV6                    0x20
 313#define VXLAN_F_UDP_ZERO_CSUM_TX        0x40
 314#define VXLAN_F_UDP_ZERO_CSUM6_TX       0x80
 315#define VXLAN_F_UDP_ZERO_CSUM6_RX       0x100
 316#define VXLAN_F_REMCSUM_TX              0x200
 317#define VXLAN_F_REMCSUM_RX              0x400
 318#define VXLAN_F_GBP                     0x800
 319#define VXLAN_F_REMCSUM_NOPARTIAL       0x1000
 320#define VXLAN_F_COLLECT_METADATA        0x2000
 321#define VXLAN_F_GPE                     0x4000
 322#define VXLAN_F_IPV6_LINKLOCAL          0x8000
 323#define VXLAN_F_TTL_INHERIT             0x10000
 324#define VXLAN_F_VNIFILTER               0x20000
 325
 326/* Flags that are used in the receive path. These flags must match in
 327 * order for a socket to be shareable
 328 */
 329#define VXLAN_F_RCV_FLAGS               (VXLAN_F_GBP |                  \
 330                                         VXLAN_F_GPE |                  \
 331                                         VXLAN_F_UDP_ZERO_CSUM6_RX |    \
 332                                         VXLAN_F_REMCSUM_RX |           \
 333                                         VXLAN_F_REMCSUM_NOPARTIAL |    \
 334                                         VXLAN_F_COLLECT_METADATA |     \
 335                                         VXLAN_F_VNIFILTER)
 336
 337/* Flags that can be set together with VXLAN_F_GPE. */
 338#define VXLAN_F_ALLOWED_GPE             (VXLAN_F_GPE |                  \
 339                                         VXLAN_F_IPV6 |                 \
 340                                         VXLAN_F_IPV6_LINKLOCAL |       \
 341                                         VXLAN_F_UDP_ZERO_CSUM_TX |     \
 342                                         VXLAN_F_UDP_ZERO_CSUM6_TX |    \
 343                                         VXLAN_F_UDP_ZERO_CSUM6_RX |    \
 344                                         VXLAN_F_COLLECT_METADATA  |    \
 345                                         VXLAN_F_VNIFILTER)
 346
 347struct net_device *vxlan_dev_create(struct net *net, const char *name,
 348                                    u8 name_assign_type, struct vxlan_config *conf);
 349
 350static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
 351                                                     netdev_features_t features)
 352{
 353        u8 l4_hdr = 0;
 354
 355        if (!skb->encapsulation)
 356                return features;
 357
 358        switch (vlan_get_protocol(skb)) {
 359        case htons(ETH_P_IP):
 360                l4_hdr = ip_hdr(skb)->protocol;
 361                break;
 362        case htons(ETH_P_IPV6):
 363                l4_hdr = ipv6_hdr(skb)->nexthdr;
 364                break;
 365        default:
 366                return features;
 367        }
 368
 369        if ((l4_hdr == IPPROTO_UDP) &&
 370            (skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
 371             skb->inner_protocol != htons(ETH_P_TEB) ||
 372             (skb_inner_mac_header(skb) - skb_transport_header(skb) !=
 373              sizeof(struct udphdr) + sizeof(struct vxlanhdr)) ||
 374             (skb->ip_summed != CHECKSUM_NONE &&
 375              !can_checksum_protocol(features, inner_eth_hdr(skb)->h_proto))))
 376                return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
 377
 378        return features;
 379}
 380
 381/* IP header + UDP + VXLAN + Ethernet header */
 382#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
 383/* IPv6 header + UDP + VXLAN + Ethernet header */
 384#define VXLAN6_HEADROOM (40 + 8 + 8 + 14)
 385
 386static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb)
 387{
 388        return (struct vxlanhdr *)(udp_hdr(skb) + 1);
 389}
 390
 391static inline __be32 vxlan_vni(__be32 vni_field)
 392{
 393#if defined(__BIG_ENDIAN)
 394        return (__force __be32)((__force u32)vni_field >> 8);
 395#else
 396        return (__force __be32)((__force u32)(vni_field & VXLAN_VNI_MASK) << 8);
 397#endif
 398}
 399
 400static inline __be32 vxlan_vni_field(__be32 vni)
 401{
 402#if defined(__BIG_ENDIAN)
 403        return (__force __be32)((__force u32)vni << 8);
 404#else
 405        return (__force __be32)((__force u32)vni >> 8);
 406#endif
 407}
 408
 409static inline size_t vxlan_rco_start(__be32 vni_field)
 410{
 411        return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT;
 412}
 413
 414static inline size_t vxlan_rco_offset(__be32 vni_field)
 415{
 416        return (vni_field & VXLAN_RCO_UDP) ?
 417                offsetof(struct udphdr, check) :
 418                offsetof(struct tcphdr, check);
 419}
 420
 421static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset)
 422{
 423        __be32 vni_field = cpu_to_be32(start >> VXLAN_RCO_SHIFT);
 424
 425        if (offset == offsetof(struct udphdr, check))
 426                vni_field |= VXLAN_RCO_UDP;
 427        return vni_field;
 428}
 429
 430static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs)
 431{
 432        return vs->sock->sk->sk_family;
 433}
 434
 435#if IS_ENABLED(CONFIG_IPV6)
 436
 437static inline bool vxlan_addr_any(const union vxlan_addr *ipa)
 438{
 439        if (ipa->sa.sa_family == AF_INET6)
 440                return ipv6_addr_any(&ipa->sin6.sin6_addr);
 441        else
 442                return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
 443}
 444
 445static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa)
 446{
 447        if (ipa->sa.sa_family == AF_INET6)
 448                return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr);
 449        else
 450                return ipv4_is_multicast(ipa->sin.sin_addr.s_addr);
 451}
 452
 453#else /* !IS_ENABLED(CONFIG_IPV6) */
 454
 455static inline bool vxlan_addr_any(const union vxlan_addr *ipa)
 456{
 457        return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
 458}
 459
 460static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa)
 461{
 462        return ipv4_is_multicast(ipa->sin.sin_addr.s_addr);
 463}
 464
 465#endif /* IS_ENABLED(CONFIG_IPV6) */
 466
 467static inline bool netif_is_vxlan(const struct net_device *dev)
 468{
 469        return dev->rtnl_link_ops &&
 470               !strcmp(dev->rtnl_link_ops->kind, "vxlan");
 471}
 472
 473struct switchdev_notifier_vxlan_fdb_info {
 474        struct switchdev_notifier_info info; /* must be first */
 475        union vxlan_addr remote_ip;
 476        __be16 remote_port;
 477        __be32 remote_vni;
 478        u32 remote_ifindex;
 479        u8 eth_addr[ETH_ALEN];
 480        __be32 vni;
 481        bool offloaded;
 482        bool added_by_user;
 483};
 484
 485#if IS_ENABLED(CONFIG_VXLAN)
 486int vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
 487                      struct switchdev_notifier_vxlan_fdb_info *fdb_info);
 488int vxlan_fdb_replay(const struct net_device *dev, __be32 vni,
 489                     struct notifier_block *nb,
 490                     struct netlink_ext_ack *extack);
 491void vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni);
 492
 493#else
 494static inline int
 495vxlan_fdb_find_uc(struct net_device *dev, const u8 *mac, __be32 vni,
 496                  struct switchdev_notifier_vxlan_fdb_info *fdb_info)
 497{
 498        return -ENOENT;
 499}
 500
 501static inline int vxlan_fdb_replay(const struct net_device *dev, __be32 vni,
 502                                   struct notifier_block *nb,
 503                                   struct netlink_ext_ack *extack)
 504{
 505        return -EOPNOTSUPP;
 506}
 507
 508static inline void
 509vxlan_fdb_clear_offload(const struct net_device *dev, __be32 vni)
 510{
 511}
 512#endif
 513
 514static inline void vxlan_flag_attr_error(int attrtype,
 515                                         struct netlink_ext_ack *extack)
 516{
 517#define VXLAN_FLAG(flg) \
 518        case IFLA_VXLAN_##flg: \
 519                NL_SET_ERR_MSG_MOD(extack, \
 520                                   "cannot change " #flg " flag"); \
 521                break
 522        switch (attrtype) {
 523        VXLAN_FLAG(TTL_INHERIT);
 524        VXLAN_FLAG(LEARNING);
 525        VXLAN_FLAG(PROXY);
 526        VXLAN_FLAG(RSC);
 527        VXLAN_FLAG(L2MISS);
 528        VXLAN_FLAG(L3MISS);
 529        VXLAN_FLAG(COLLECT_METADATA);
 530        VXLAN_FLAG(UDP_ZERO_CSUM6_TX);
 531        VXLAN_FLAG(UDP_ZERO_CSUM6_RX);
 532        VXLAN_FLAG(REMCSUM_TX);
 533        VXLAN_FLAG(REMCSUM_RX);
 534        VXLAN_FLAG(GBP);
 535        VXLAN_FLAG(GPE);
 536        VXLAN_FLAG(REMCSUM_NOPARTIAL);
 537        default:
 538                NL_SET_ERR_MSG_MOD(extack, \
 539                                   "cannot change flag");
 540                break;
 541        }
 542#undef VXLAN_FLAG
 543}
 544
 545static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,
 546                                            int hash,
 547                                            struct vxlan_rdst *rdst)
 548{
 549        struct fib_nh_common *nhc;
 550
 551        nhc = nexthop_path_fdb_result(nh, hash);
 552        if (unlikely(!nhc))
 553                return false;
 554
 555        switch (nhc->nhc_gw_family) {
 556        case AF_INET:
 557                rdst->remote_ip.sin.sin_addr.s_addr = nhc->nhc_gw.ipv4;
 558                rdst->remote_ip.sa.sa_family = AF_INET;
 559                break;
 560        case AF_INET6:
 561                rdst->remote_ip.sin6.sin6_addr = nhc->nhc_gw.ipv6;
 562                rdst->remote_ip.sa.sa_family = AF_INET6;
 563                break;
 564        }
 565
 566        return true;
 567}
 568
 569#endif
 570