if_vxlan.c (e25152834cdf3b353892835a4f3b157e066a8ed4) if_vxlan.c (b092fd6c973dab0ffaca8144f435c91a2588aa21)
1/*-
2 * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org>
3 * All rights reserved.
1/*-
2 * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org>
3 * All rights reserved.
4 * Copyright (c) 2020, Chelsio Communications.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright

--- 43 unchanged lines hidden (view full) ---

55#include <net/if.h>
56#include <net/if_var.h>
57#include <net/if_clone.h>
58#include <net/if_dl.h>
59#include <net/if_media.h>
60#include <net/if_types.h>
61#include <net/if_vxlan.h>
62#include <net/netisr.h>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright

--- 43 unchanged lines hidden (view full) ---

56#include <net/if.h>
57#include <net/if_var.h>
58#include <net/if_clone.h>
59#include <net/if_dl.h>
60#include <net/if_media.h>
61#include <net/if_types.h>
62#include <net/if_vxlan.h>
63#include <net/netisr.h>
64#include <net/route.h>
65#include <net/route/nhop.h>
63
64#include <netinet/in.h>
65#include <netinet/in_systm.h>
66#include <netinet/in_var.h>
67#include <netinet/in_pcb.h>
68#include <netinet/ip.h>
69#include <netinet/ip6.h>
70#include <netinet/ip_var.h>
71#include <netinet/udp.h>
72#include <netinet/udp_var.h>
66
67#include <netinet/in.h>
68#include <netinet/in_systm.h>
69#include <netinet/in_var.h>
70#include <netinet/in_pcb.h>
71#include <netinet/ip.h>
72#include <netinet/ip6.h>
73#include <netinet/ip_var.h>
74#include <netinet/udp.h>
75#include <netinet/udp_var.h>
76#include <netinet/in_fib.h>
77#include <netinet6/in6_fib.h>
73
74#include <netinet6/ip6_var.h>
75#include <netinet6/scope6_var.h>
76
77struct vxlan_softc;
78LIST_HEAD(vxlan_softc_head, vxlan_softc);
79
78
79#include <netinet6/ip6_var.h>
80#include <netinet6/scope6_var.h>
81
82struct vxlan_softc;
83LIST_HEAD(vxlan_softc_head, vxlan_softc);
84
85struct sx vxlan_sx;
86SX_SYSINIT(vxlan, &vxlan_sx, "VXLAN global start/stop lock");
87
80struct vxlan_socket_mc_info {
81 union vxlan_sockaddr vxlsomc_saddr;
82 union vxlan_sockaddr vxlsomc_gaddr;
83 int vxlsomc_ifidx;
84 int vxlsomc_users;
85};
86
87/*
88 * The maximum MTU of encapsulated ethernet frame within IPv4/UDP packet.
89 */
90#define VXLAN_MAX_MTU (IP_MAXPACKET - \
91 60 /* Maximum IPv4 header len */ - \
92 sizeof(struct udphdr) - \
93 sizeof(struct vxlan_header) - \
94 ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN)
88struct vxlan_socket_mc_info {
89 union vxlan_sockaddr vxlsomc_saddr;
90 union vxlan_sockaddr vxlsomc_gaddr;
91 int vxlsomc_ifidx;
92 int vxlsomc_users;
93};
94
95/*
96 * The maximum MTU of encapsulated ethernet frame within IPv4/UDP packet.
97 */
98#define VXLAN_MAX_MTU (IP_MAXPACKET - \
99 60 /* Maximum IPv4 header len */ - \
100 sizeof(struct udphdr) - \
101 sizeof(struct vxlan_header) - \
102 ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN)
103#define VXLAN_BASIC_IFCAPS (IFCAP_LINKSTATE | IFCAP_JUMBO_MTU)
95
96#define VXLAN_SO_MC_MAX_GROUPS 32
97
98#define VXLAN_SO_VNI_HASH_SHIFT 6
99#define VXLAN_SO_VNI_HASH_SIZE (1 << VXLAN_SO_VNI_HASH_SHIFT)
100#define VXLAN_SO_VNI_HASH(_vni) ((_vni) % VXLAN_SO_VNI_HASH_SIZE)
101
102struct vxlan_socket {

--- 38 unchanged lines hidden (view full) ---

141#define VXLAN_SC_FTABLE_HASH(_sc, _mac) \
142 (vxlan_mac_hash(_sc, _mac) % VXLAN_SC_FTABLE_SIZE)
143
144LIST_HEAD(vxlan_ftable_head, vxlan_ftable_entry);
145
146struct vxlan_statistics {
147 uint32_t ftable_nospace;
148 uint32_t ftable_lock_upgrade_failed;
104
105#define VXLAN_SO_MC_MAX_GROUPS 32
106
107#define VXLAN_SO_VNI_HASH_SHIFT 6
108#define VXLAN_SO_VNI_HASH_SIZE (1 << VXLAN_SO_VNI_HASH_SHIFT)
109#define VXLAN_SO_VNI_HASH(_vni) ((_vni) % VXLAN_SO_VNI_HASH_SIZE)
110
111struct vxlan_socket {

--- 38 unchanged lines hidden (view full) ---

150#define VXLAN_SC_FTABLE_HASH(_sc, _mac) \
151 (vxlan_mac_hash(_sc, _mac) % VXLAN_SC_FTABLE_SIZE)
152
153LIST_HEAD(vxlan_ftable_head, vxlan_ftable_entry);
154
155struct vxlan_statistics {
156 uint32_t ftable_nospace;
157 uint32_t ftable_lock_upgrade_failed;
158 counter_u64_t txcsum;
159 counter_u64_t tso;
160 counter_u64_t rxcsum;
149};
150
151struct vxlan_softc {
152 struct ifnet *vxl_ifp;
161};
162
163struct vxlan_softc {
164 struct ifnet *vxl_ifp;
165 int vxl_reqcap;
153 struct vxlan_socket *vxl_sock;
154 uint32_t vxl_vni;
155 union vxlan_sockaddr vxl_src_addr;
156 union vxlan_sockaddr vxl_dst_addr;
157 uint32_t vxl_flags;
158#define VXLAN_FLAG_INIT 0x0001
159#define VXLAN_FLAG_TEARDOWN 0x0002
160#define VXLAN_FLAG_LEARN 0x0004

--- 27 unchanged lines hidden (view full) ---

188 struct callout vxl_callout;
189 struct ether_addr vxl_hwaddr;
190 int vxl_mc_ifindex;
191 struct ifnet *vxl_mc_ifp;
192 struct ifmedia vxl_media;
193 char vxl_mc_ifname[IFNAMSIZ];
194 LIST_ENTRY(vxlan_softc) vxl_entry;
195 LIST_ENTRY(vxlan_softc) vxl_ifdetach_list;
166 struct vxlan_socket *vxl_sock;
167 uint32_t vxl_vni;
168 union vxlan_sockaddr vxl_src_addr;
169 union vxlan_sockaddr vxl_dst_addr;
170 uint32_t vxl_flags;
171#define VXLAN_FLAG_INIT 0x0001
172#define VXLAN_FLAG_TEARDOWN 0x0002
173#define VXLAN_FLAG_LEARN 0x0004

--- 27 unchanged lines hidden (view full) ---

201 struct callout vxl_callout;
202 struct ether_addr vxl_hwaddr;
203 int vxl_mc_ifindex;
204 struct ifnet *vxl_mc_ifp;
205 struct ifmedia vxl_media;
206 char vxl_mc_ifname[IFNAMSIZ];
207 LIST_ENTRY(vxlan_softc) vxl_entry;
208 LIST_ENTRY(vxlan_softc) vxl_ifdetach_list;
209
210 /* For rate limiting errors on the tx fast path. */
211 struct timeval err_time;
212 int err_pps;
196};
197
198#define VXLAN_RLOCK(_sc, _p) rm_rlock(&(_sc)->vxl_lock, (_p))
199#define VXLAN_RUNLOCK(_sc, _p) rm_runlock(&(_sc)->vxl_lock, (_p))
200#define VXLAN_WLOCK(_sc) rm_wlock(&(_sc)->vxl_lock)
201#define VXLAN_WUNLOCK(_sc) rm_wunlock(&(_sc)->vxl_lock)
202#define VXLAN_LOCK_WOWNED(_sc) rm_wowned(&(_sc)->vxl_lock)
203#define VXLAN_LOCK_ASSERT(_sc) rm_assert(&(_sc)->vxl_lock, RA_LOCKED)

--- 88 unchanged lines hidden (view full) ---

292
293static struct ifnet *
294 vxlan_multicast_if_ref(struct vxlan_softc *, int);
295static void vxlan_free_multicast(struct vxlan_softc *);
296static int vxlan_setup_multicast_interface(struct vxlan_softc *);
297
298static int vxlan_setup_multicast(struct vxlan_softc *);
299static int vxlan_setup_socket(struct vxlan_softc *);
213};
214
215#define VXLAN_RLOCK(_sc, _p) rm_rlock(&(_sc)->vxl_lock, (_p))
216#define VXLAN_RUNLOCK(_sc, _p) rm_runlock(&(_sc)->vxl_lock, (_p))
217#define VXLAN_WLOCK(_sc) rm_wlock(&(_sc)->vxl_lock)
218#define VXLAN_WUNLOCK(_sc) rm_wunlock(&(_sc)->vxl_lock)
219#define VXLAN_LOCK_WOWNED(_sc) rm_wowned(&(_sc)->vxl_lock)
220#define VXLAN_LOCK_ASSERT(_sc) rm_assert(&(_sc)->vxl_lock, RA_LOCKED)

--- 88 unchanged lines hidden (view full) ---

309
310static struct ifnet *
311 vxlan_multicast_if_ref(struct vxlan_softc *, int);
312static void vxlan_free_multicast(struct vxlan_softc *);
313static int vxlan_setup_multicast_interface(struct vxlan_softc *);
314
315static int vxlan_setup_multicast(struct vxlan_softc *);
316static int vxlan_setup_socket(struct vxlan_softc *);
300static void vxlan_setup_interface(struct vxlan_softc *);
317#ifdef INET6
318static void vxlan_setup_zero_checksum_port(struct vxlan_softc *);
319#endif
320static void vxlan_setup_interface_hdrlen(struct vxlan_softc *);
301static int vxlan_valid_init_config(struct vxlan_softc *);
302static void vxlan_init_wait(struct vxlan_softc *);
303static void vxlan_init_complete(struct vxlan_softc *);
304static void vxlan_init(void *);
305static void vxlan_release(struct vxlan_softc *);
306static void vxlan_teardown_wait(struct vxlan_softc *);
307static void vxlan_teardown_complete(struct vxlan_softc *);
308static void vxlan_teardown_locked(struct vxlan_softc *);

--- 33 unchanged lines hidden (view full) ---

342 const union vxlan_sockaddr *, struct mbuf *);
343static int vxlan_transmit(struct ifnet *, struct mbuf *);
344static void vxlan_qflush(struct ifnet *);
345static void vxlan_rcv_udp_packet(struct mbuf *, int, struct inpcb *,
346 const struct sockaddr *, void *);
347static int vxlan_input(struct vxlan_socket *, uint32_t, struct mbuf **,
348 const struct sockaddr *);
349
321static int vxlan_valid_init_config(struct vxlan_softc *);
322static void vxlan_init_wait(struct vxlan_softc *);
323static void vxlan_init_complete(struct vxlan_softc *);
324static void vxlan_init(void *);
325static void vxlan_release(struct vxlan_softc *);
326static void vxlan_teardown_wait(struct vxlan_softc *);
327static void vxlan_teardown_complete(struct vxlan_softc *);
328static void vxlan_teardown_locked(struct vxlan_softc *);

--- 33 unchanged lines hidden (view full) ---

362 const union vxlan_sockaddr *, struct mbuf *);
363static int vxlan_transmit(struct ifnet *, struct mbuf *);
364static void vxlan_qflush(struct ifnet *);
365static void vxlan_rcv_udp_packet(struct mbuf *, int, struct inpcb *,
366 const struct sockaddr *, void *);
367static int vxlan_input(struct vxlan_socket *, uint32_t, struct mbuf **,
368 const struct sockaddr *);
369
370static int vxlan_stats_alloc(struct vxlan_softc *);
371static void vxlan_stats_free(struct vxlan_softc *);
350static void vxlan_set_default_config(struct vxlan_softc *);
351static int vxlan_set_user_config(struct vxlan_softc *,
352 struct ifvxlanparam *);
372static void vxlan_set_default_config(struct vxlan_softc *);
373static int vxlan_set_user_config(struct vxlan_softc *,
374 struct ifvxlanparam *);
375static int vxlan_set_reqcap(struct vxlan_softc *, struct ifnet *, int);
376static void vxlan_set_hwcaps(struct vxlan_softc *);
353static int vxlan_clone_create(struct if_clone *, int, caddr_t);
354static void vxlan_clone_destroy(struct ifnet *);
355
356static uint32_t vxlan_mac_hash(struct vxlan_softc *, const uint8_t *);
357static int vxlan_media_change(struct ifnet *);
358static void vxlan_media_status(struct ifnet *, struct ifmediareq *);
359
360static int vxlan_sockaddr_cmp(const union vxlan_sockaddr *,

--- 1189 unchanged lines hidden (view full) ---

1550 if (multicast != 0)
1551 vxlan_free_multicast(sc);
1552 vxlan_socket_release(vso);
1553 }
1554
1555 return (error);
1556}
1557
377static int vxlan_clone_create(struct if_clone *, int, caddr_t);
378static void vxlan_clone_destroy(struct ifnet *);
379
380static uint32_t vxlan_mac_hash(struct vxlan_softc *, const uint8_t *);
381static int vxlan_media_change(struct ifnet *);
382static void vxlan_media_status(struct ifnet *, struct ifmediareq *);
383
384static int vxlan_sockaddr_cmp(const union vxlan_sockaddr *,

--- 1189 unchanged lines hidden (view full) ---

1574 if (multicast != 0)
1575 vxlan_free_multicast(sc);
1576 vxlan_socket_release(vso);
1577 }
1578
1579 return (error);
1580}
1581
1582#ifdef INET6
1558static void
1583static void
1559vxlan_setup_interface(struct vxlan_softc *sc)
1584vxlan_setup_zero_checksum_port(struct vxlan_softc *sc)
1560{
1585{
1586
1587 if (!VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_src_addr))
1588 return;
1589
1590 MPASS(sc->vxl_src_addr.in6.sin6_port != 0);
1591 MPASS(sc->vxl_dst_addr.in6.sin6_port != 0);
1592
1593 if (sc->vxl_src_addr.in6.sin6_port != sc->vxl_dst_addr.in6.sin6_port) {
1594 if_printf(sc->vxl_ifp, "port %d in src address does not match "
1595 "port %d in dst address, rfc6935_port (%d) not updated.\n",
1596 ntohs(sc->vxl_src_addr.in6.sin6_port),
1597 ntohs(sc->vxl_dst_addr.in6.sin6_port),
1598 V_zero_checksum_port);
1599 return;
1600 }
1601
1602 if (V_zero_checksum_port != 0) {
1603 if (V_zero_checksum_port !=
1604 ntohs(sc->vxl_src_addr.in6.sin6_port)) {
1605 if_printf(sc->vxl_ifp, "rfc6935_port is already set to "
1606 "%d, cannot set it to %d.\n", V_zero_checksum_port,
1607 ntohs(sc->vxl_src_addr.in6.sin6_port));
1608 }
1609 return;
1610 }
1611
1612 V_zero_checksum_port = ntohs(sc->vxl_src_addr.in6.sin6_port);
1613 if_printf(sc->vxl_ifp, "rfc6935_port set to %d\n",
1614 V_zero_checksum_port);
1615}
1616#endif
1617
1618static void
1619vxlan_setup_interface_hdrlen(struct vxlan_softc *sc)
1620{
1561 struct ifnet *ifp;
1562
1563 ifp = sc->vxl_ifp;
1564 ifp->if_hdrlen = ETHER_HDR_LEN + sizeof(struct vxlanudphdr);
1565
1566 if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_dst_addr) != 0)
1567 ifp->if_hdrlen += sizeof(struct ip);
1568 else if (VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_dst_addr) != 0)

--- 81 unchanged lines hidden (view full) ---

1650{
1651 static const uint8_t empty_mac[ETHER_ADDR_LEN];
1652 struct vxlan_softc *sc;
1653 struct ifnet *ifp;
1654
1655 sc = xsc;
1656 ifp = sc->vxl_ifp;
1657
1621 struct ifnet *ifp;
1622
1623 ifp = sc->vxl_ifp;
1624 ifp->if_hdrlen = ETHER_HDR_LEN + sizeof(struct vxlanudphdr);
1625
1626 if (VXLAN_SOCKADDR_IS_IPV4(&sc->vxl_dst_addr) != 0)
1627 ifp->if_hdrlen += sizeof(struct ip);
1628 else if (VXLAN_SOCKADDR_IS_IPV6(&sc->vxl_dst_addr) != 0)

--- 81 unchanged lines hidden (view full) ---

1710{
1711 static const uint8_t empty_mac[ETHER_ADDR_LEN];
1712 struct vxlan_softc *sc;
1713 struct ifnet *ifp;
1714
1715 sc = xsc;
1716 ifp = sc->vxl_ifp;
1717
1718 sx_xlock(&vxlan_sx);
1658 VXLAN_WLOCK(sc);
1659 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1660 VXLAN_WUNLOCK(sc);
1719 VXLAN_WLOCK(sc);
1720 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1721 VXLAN_WUNLOCK(sc);
1722 sx_xunlock(&vxlan_sx);
1661 return;
1662 }
1663 sc->vxl_flags |= VXLAN_FLAG_INIT;
1664 VXLAN_WUNLOCK(sc);
1665
1666 if (vxlan_valid_init_config(sc) != 0)
1667 goto out;
1668
1723 return;
1724 }
1725 sc->vxl_flags |= VXLAN_FLAG_INIT;
1726 VXLAN_WUNLOCK(sc);
1727
1728 if (vxlan_valid_init_config(sc) != 0)
1729 goto out;
1730
1669 vxlan_setup_interface(sc);
1670
1671 if (vxlan_setup_socket(sc) != 0)
1672 goto out;
1673
1731 if (vxlan_setup_socket(sc) != 0)
1732 goto out;
1733
1734#ifdef INET6
1735 vxlan_setup_zero_checksum_port(sc);
1736#endif
1737
1674 /* Initialize the default forwarding entry. */
1675 vxlan_ftable_entry_init(sc, &sc->vxl_default_fe, empty_mac,
1676 &sc->vxl_dst_addr.sa, VXLAN_FE_FLAG_STATIC);
1677
1678 VXLAN_WLOCK(sc);
1679 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1680 callout_reset(&sc->vxl_callout, vxlan_ftable_prune_period * hz,
1681 vxlan_timer, sc);
1682 VXLAN_WUNLOCK(sc);
1683
1684 if_link_state_change(ifp, LINK_STATE_UP);
1738 /* Initialize the default forwarding entry. */
1739 vxlan_ftable_entry_init(sc, &sc->vxl_default_fe, empty_mac,
1740 &sc->vxl_dst_addr.sa, VXLAN_FE_FLAG_STATIC);
1741
1742 VXLAN_WLOCK(sc);
1743 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1744 callout_reset(&sc->vxl_callout, vxlan_ftable_prune_period * hz,
1745 vxlan_timer, sc);
1746 VXLAN_WUNLOCK(sc);
1747
1748 if_link_state_change(ifp, LINK_STATE_UP);
1749
1750 EVENTHANDLER_INVOKE(vxlan_start, ifp, sc->vxl_src_addr.in4.sin_family,
1751 ntohs(sc->vxl_src_addr.in4.sin_port));
1685out:
1686 vxlan_init_complete(sc);
1752out:
1753 vxlan_init_complete(sc);
1754 sx_xunlock(&vxlan_sx);
1687}
1688
1689static void
1690vxlan_release(struct vxlan_softc *sc)
1691{
1692
1693 /*
1694 * The softc may be destroyed as soon as we release our reference,

--- 25 unchanged lines hidden (view full) ---

1720}
1721
1722static void
1723vxlan_teardown_locked(struct vxlan_softc *sc)
1724{
1725 struct ifnet *ifp;
1726 struct vxlan_socket *vso;
1727
1755}
1756
1757static void
1758vxlan_release(struct vxlan_softc *sc)
1759{
1760
1761 /*
1762 * The softc may be destroyed as soon as we release our reference,

--- 25 unchanged lines hidden (view full) ---

1788}
1789
1790static void
1791vxlan_teardown_locked(struct vxlan_softc *sc)
1792{
1793 struct ifnet *ifp;
1794 struct vxlan_socket *vso;
1795
1728 ifp = sc->vxl_ifp;
1729
1796 sx_assert(&vxlan_sx, SA_XLOCKED);
1730 VXLAN_LOCK_WASSERT(sc);
1731 MPASS(sc->vxl_flags & VXLAN_FLAG_TEARDOWN);
1732
1797 VXLAN_LOCK_WASSERT(sc);
1798 MPASS(sc->vxl_flags & VXLAN_FLAG_TEARDOWN);
1799
1800 ifp = sc->vxl_ifp;
1733 ifp->if_flags &= ~IFF_UP;
1734 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1735 callout_stop(&sc->vxl_callout);
1736 vso = sc->vxl_sock;
1737 sc->vxl_sock = NULL;
1738
1739 VXLAN_WUNLOCK(sc);
1740 if_link_state_change(ifp, LINK_STATE_DOWN);
1801 ifp->if_flags &= ~IFF_UP;
1802 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1803 callout_stop(&sc->vxl_callout);
1804 vso = sc->vxl_sock;
1805 sc->vxl_sock = NULL;
1806
1807 VXLAN_WUNLOCK(sc);
1808 if_link_state_change(ifp, LINK_STATE_DOWN);
1809 EVENTHANDLER_INVOKE(vxlan_stop, ifp, sc->vxl_src_addr.in4.sin_family,
1810 ntohs(sc->vxl_src_addr.in4.sin_port));
1741
1742 if (vso != NULL) {
1743 vxlan_socket_remove_softc(vso, sc);
1744
1745 if (sc->vxl_vso_mc_index != -1) {
1746 vxlan_socket_mc_release_group_by_idx(vso,
1747 sc->vxl_vso_mc_index);
1748 sc->vxl_vso_mc_index = -1;

--- 13 unchanged lines hidden (view full) ---

1762
1763 vxlan_teardown_complete(sc);
1764}
1765
1766static void
1767vxlan_teardown(struct vxlan_softc *sc)
1768{
1769
1811
1812 if (vso != NULL) {
1813 vxlan_socket_remove_softc(vso, sc);
1814
1815 if (sc->vxl_vso_mc_index != -1) {
1816 vxlan_socket_mc_release_group_by_idx(vso,
1817 sc->vxl_vso_mc_index);
1818 sc->vxl_vso_mc_index = -1;

--- 13 unchanged lines hidden (view full) ---

1832
1833 vxlan_teardown_complete(sc);
1834}
1835
1836static void
1837vxlan_teardown(struct vxlan_softc *sc)
1838{
1839
1840 sx_xlock(&vxlan_sx);
1770 VXLAN_WLOCK(sc);
1771 if (sc->vxl_flags & VXLAN_FLAG_TEARDOWN) {
1772 vxlan_teardown_wait(sc);
1773 VXLAN_WUNLOCK(sc);
1841 VXLAN_WLOCK(sc);
1842 if (sc->vxl_flags & VXLAN_FLAG_TEARDOWN) {
1843 vxlan_teardown_wait(sc);
1844 VXLAN_WUNLOCK(sc);
1845 sx_xunlock(&vxlan_sx);
1774 return;
1775 }
1776
1777 sc->vxl_flags |= VXLAN_FLAG_TEARDOWN;
1778 vxlan_teardown_locked(sc);
1846 return;
1847 }
1848
1849 sc->vxl_flags |= VXLAN_FLAG_TEARDOWN;
1850 vxlan_teardown_locked(sc);
1851 sx_xunlock(&vxlan_sx);
1779}
1780
1781static void
1782vxlan_ifdetach(struct vxlan_softc *sc, struct ifnet *ifp,
1783 struct vxlan_softc_head *list)
1784{
1785
1786 VXLAN_WLOCK(sc);

--- 115 unchanged lines hidden (view full) ---

1902 error = vxlan_sockaddr_in6_embedscope(vxlsa);
1903 if (error)
1904 return (error);
1905 }
1906
1907 VXLAN_WLOCK(sc);
1908 if (vxlan_can_change_config(sc)) {
1909 vxlan_sockaddr_in_copy(&sc->vxl_src_addr, &vxlsa->sa);
1852}
1853
1854static void
1855vxlan_ifdetach(struct vxlan_softc *sc, struct ifnet *ifp,
1856 struct vxlan_softc_head *list)
1857{
1858
1859 VXLAN_WLOCK(sc);

--- 115 unchanged lines hidden (view full) ---

1975 error = vxlan_sockaddr_in6_embedscope(vxlsa);
1976 if (error)
1977 return (error);
1978 }
1979
1980 VXLAN_WLOCK(sc);
1981 if (vxlan_can_change_config(sc)) {
1982 vxlan_sockaddr_in_copy(&sc->vxl_src_addr, &vxlsa->sa);
1983 vxlan_set_hwcaps(sc);
1910 error = 0;
1911 } else
1912 error = EBUSY;
1913 VXLAN_WUNLOCK(sc);
1914
1915 return (error);
1916}
1917

--- 13 unchanged lines hidden (view full) ---

1931 error = vxlan_sockaddr_in6_embedscope(vxlsa);
1932 if (error)
1933 return (error);
1934 }
1935
1936 VXLAN_WLOCK(sc);
1937 if (vxlan_can_change_config(sc)) {
1938 vxlan_sockaddr_in_copy(&sc->vxl_dst_addr, &vxlsa->sa);
1984 error = 0;
1985 } else
1986 error = EBUSY;
1987 VXLAN_WUNLOCK(sc);
1988
1989 return (error);
1990}
1991

--- 13 unchanged lines hidden (view full) ---

2005 error = vxlan_sockaddr_in6_embedscope(vxlsa);
2006 if (error)
2007 return (error);
2008 }
2009
2010 VXLAN_WLOCK(sc);
2011 if (vxlan_can_change_config(sc)) {
2012 vxlan_sockaddr_in_copy(&sc->vxl_dst_addr, &vxlsa->sa);
2013 vxlan_setup_interface_hdrlen(sc);
1939 error = 0;
1940 } else
1941 error = EBUSY;
1942 VXLAN_WUNLOCK(sc);
1943
1944 return (error);
1945}
1946

--- 111 unchanged lines hidden (view full) ---

2058 struct ifvxlancmd *cmd;
2059 int error;
2060
2061 cmd = arg;
2062
2063 VXLAN_WLOCK(sc);
2064 if (vxlan_can_change_config(sc)) {
2065 strlcpy(sc->vxl_mc_ifname, cmd->vxlcmd_ifname, IFNAMSIZ);
2014 error = 0;
2015 } else
2016 error = EBUSY;
2017 VXLAN_WUNLOCK(sc);
2018
2019 return (error);
2020}
2021

--- 111 unchanged lines hidden (view full) ---

2133 struct ifvxlancmd *cmd;
2134 int error;
2135
2136 cmd = arg;
2137
2138 VXLAN_WLOCK(sc);
2139 if (vxlan_can_change_config(sc)) {
2140 strlcpy(sc->vxl_mc_ifname, cmd->vxlcmd_ifname, IFNAMSIZ);
2141 vxlan_set_hwcaps(sc);
2066 error = 0;
2067 } else
2068 error = EBUSY;
2069 VXLAN_WUNLOCK(sc);
2070
2071 return (error);
2072}
2073

--- 205 unchanged lines hidden (view full) ---

2279
2280 case SIOCSIFMTU:
2281 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > VXLAN_MAX_MTU)
2282 error = EINVAL;
2283 else
2284 ifp->if_mtu = ifr->ifr_mtu;
2285 break;
2286
2142 error = 0;
2143 } else
2144 error = EBUSY;
2145 VXLAN_WUNLOCK(sc);
2146
2147 return (error);
2148}
2149

--- 205 unchanged lines hidden (view full) ---

2355
2356 case SIOCSIFMTU:
2357 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > VXLAN_MAX_MTU)
2358 error = EINVAL;
2359 else
2360 ifp->if_mtu = ifr->ifr_mtu;
2361 break;
2362
2363 case SIOCSIFCAP:
2364 VXLAN_WLOCK(sc);
2365 error = vxlan_set_reqcap(sc, ifp, ifr->ifr_reqcap);
2366 if (error == 0)
2367 vxlan_set_hwcaps(sc);
2368 VXLAN_WUNLOCK(sc);
2369 break;
2370
2287 default:
2288 error = ether_ioctl(ifp, cmd, data);
2289 break;
2290 }
2291
2292 return (error);
2293}
2294

--- 35 unchanged lines hidden (view full) ---

2330 udph->uh_sum = 0;
2331
2332 vxh = &hdr->vxlh_hdr;
2333 vxh->vxlh_flags = htonl(VXLAN_HDR_FLAGS_VALID_VNI);
2334 vxh->vxlh_vni = htonl(sc->vxl_vni << VXLAN_HDR_VNI_SHIFT);
2335}
2336#endif
2337
2371 default:
2372 error = ether_ioctl(ifp, cmd, data);
2373 break;
2374 }
2375
2376 return (error);
2377}
2378

--- 35 unchanged lines hidden (view full) ---

2414 udph->uh_sum = 0;
2415
2416 vxh = &hdr->vxlh_hdr;
2417 vxh->vxlh_flags = htonl(VXLAN_HDR_FLAGS_VALID_VNI);
2418 vxh->vxlh_vni = htonl(sc->vxl_vni << VXLAN_HDR_VNI_SHIFT);
2419}
2420#endif
2421
2422/*
2423 * Return the CSUM_INNER_* equivalent of CSUM_* caps.
2424 */
2425static uint32_t
2426csum_flags_to_inner_flags(uint32_t csum_flags_in, uint32_t encap)
2427{
2428 uint32_t csum_flags = CSUM_ENCAP_VXLAN;
2429 const uint32_t v4 = CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP;
2430
2431 /*
2432 * csum_flags can request either v4 or v6 offload but not both.
2433 * tcp_output always sets CSUM_TSO (both CSUM_IP_TSO and CSUM_IP6_TSO)
2434 * so those bits are no good to detect the IP version. Other bits are
2435 * always set with CSUM_TSO and we use those to figure out the IP
2436 * version.
2437 */
2438 if (csum_flags_in & v4) {
2439 if (csum_flags_in & CSUM_IP)
2440 csum_flags |= CSUM_INNER_IP;
2441 if (csum_flags_in & CSUM_IP_UDP)
2442 csum_flags |= CSUM_INNER_IP_UDP;
2443 if (csum_flags_in & CSUM_IP_TCP)
2444 csum_flags |= CSUM_INNER_IP_TCP;
2445 if (csum_flags_in & CSUM_IP_TSO)
2446 csum_flags |= CSUM_INNER_IP_TSO;
2447 } else {
2448#ifdef INVARIANTS
2449 const uint32_t v6 = CSUM_IP6_UDP | CSUM_IP6_TCP;
2450
2451 MPASS((csum_flags_in & v6) != 0);
2452#endif
2453 if (csum_flags_in & CSUM_IP6_UDP)
2454 csum_flags |= CSUM_INNER_IP6_UDP;
2455 if (csum_flags_in & CSUM_IP6_TCP)
2456 csum_flags |= CSUM_INNER_IP6_TCP;
2457 if (csum_flags_in & CSUM_IP6_TSO)
2458 csum_flags |= CSUM_INNER_IP6_TSO;
2459 }
2460
2461 return (csum_flags);
2462}
2463
2338static int
2339vxlan_encap4(struct vxlan_softc *sc, const union vxlan_sockaddr *fvxlsa,
2340 struct mbuf *m)
2341{
2342#ifdef INET
2343 struct ifnet *ifp;
2344 struct ip *ip;
2345 struct in_addr srcaddr, dstaddr;
2346 uint16_t srcport, dstport;
2347 int len, mcast, error;
2464static int
2465vxlan_encap4(struct vxlan_softc *sc, const union vxlan_sockaddr *fvxlsa,
2466 struct mbuf *m)
2467{
2468#ifdef INET
2469 struct ifnet *ifp;
2470 struct ip *ip;
2471 struct in_addr srcaddr, dstaddr;
2472 uint16_t srcport, dstport;
2473 int len, mcast, error;
2474 struct route route, *ro;
2475 struct sockaddr_in *sin;
2476 uint32_t csum_flags;
2348
2477
2478 NET_EPOCH_ASSERT();
2479
2349 ifp = sc->vxl_ifp;
2350 srcaddr = sc->vxl_src_addr.in4.sin_addr;
2351 srcport = vxlan_pick_source_port(sc, m);
2352 dstaddr = fvxlsa->in4.sin_addr;
2353 dstport = fvxlsa->in4.sin_port;
2354
2355 M_PREPEND(m, sizeof(struct ip) + sizeof(struct vxlanudphdr),
2356 M_NOWAIT);

--- 14 unchanged lines hidden (view full) ---

2371 ip->ip_src = srcaddr;
2372 ip->ip_dst = dstaddr;
2373
2374 vxlan_encap_header(sc, m, sizeof(struct ip), srcport, dstport);
2375
2376 mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
2377 m->m_flags &= ~(M_MCAST | M_BCAST);
2378
2480 ifp = sc->vxl_ifp;
2481 srcaddr = sc->vxl_src_addr.in4.sin_addr;
2482 srcport = vxlan_pick_source_port(sc, m);
2483 dstaddr = fvxlsa->in4.sin_addr;
2484 dstport = fvxlsa->in4.sin_port;
2485
2486 M_PREPEND(m, sizeof(struct ip) + sizeof(struct vxlanudphdr),
2487 M_NOWAIT);

--- 14 unchanged lines hidden (view full) ---

2502 ip->ip_src = srcaddr;
2503 ip->ip_dst = dstaddr;
2504
2505 vxlan_encap_header(sc, m, sizeof(struct ip), srcport, dstport);
2506
2507 mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
2508 m->m_flags &= ~(M_MCAST | M_BCAST);
2509
2379 error = ip_output(m, NULL, NULL, 0, sc->vxl_im4o, NULL);
2510 m->m_pkthdr.csum_flags &= CSUM_FLAGS_TX;
2511 if (m->m_pkthdr.csum_flags != 0) {
2512 /*
2513 * HW checksum (L3 and/or L4) or TSO has been requested. Look
2514 * up the ifnet for the outbound route and verify that the
2515 * outbound ifnet can perform the requested operation on the
2516 * inner frame.
2517 */
2518 bzero(&route, sizeof(route));
2519 ro = &route;
2520 sin = (struct sockaddr_in *)&ro->ro_dst;
2521 sin->sin_family = AF_INET;
2522 sin->sin_len = sizeof(*sin);
2523 sin->sin_addr = ip->ip_dst;
2524 ro->ro_nh = fib4_lookup(RT_DEFAULT_FIB, ip->ip_dst, 0, NHR_NONE,
2525 0);
2526 if (ro->ro_nh == NULL) {
2527 m_freem(m);
2528 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2529 return (EHOSTUNREACH);
2530 }
2531
2532 csum_flags = csum_flags_to_inner_flags(m->m_pkthdr.csum_flags,
2533 CSUM_ENCAP_VXLAN);
2534 if ((csum_flags & ro->ro_nh->nh_ifp->if_hwassist) !=
2535 csum_flags) {
2536 if (ppsratecheck(&sc->err_time, &sc->err_pps, 1)) {
2537 const struct ifnet *nh_ifp = ro->ro_nh->nh_ifp;
2538
2539 if_printf(ifp, "interface %s is missing hwcaps "
2540 "0x%08x, csum_flags 0x%08x -> 0x%08x, "
2541 "hwassist 0x%08x\n", nh_ifp->if_xname,
2542 csum_flags & ~(uint32_t)nh_ifp->if_hwassist,
2543 m->m_pkthdr.csum_flags, csum_flags,
2544 (uint32_t)nh_ifp->if_hwassist);
2545 }
2546 m_freem(m);
2547 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2548 return (ENXIO);
2549 }
2550 m->m_pkthdr.csum_flags = csum_flags;
2551 if (csum_flags &
2552 (CSUM_INNER_IP | CSUM_INNER_IP_UDP | CSUM_INNER_IP6_UDP |
2553 CSUM_INNER_IP_TCP | CSUM_INNER_IP6_TCP)) {
2554 counter_u64_add(sc->vxl_stats.txcsum, 1);
2555 if (csum_flags & CSUM_INNER_TSO)
2556 counter_u64_add(sc->vxl_stats.tso, 1);
2557 }
2558 } else
2559 ro = NULL;
2560 error = ip_output(m, NULL, ro, 0, sc->vxl_im4o, NULL);
2380 if (error == 0) {
2381 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2382 if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
2383 if (mcast != 0)
2384 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
2385 } else
2386 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2387

--- 9 unchanged lines hidden (view full) ---

2397 struct mbuf *m)
2398{
2399#ifdef INET6
2400 struct ifnet *ifp;
2401 struct ip6_hdr *ip6;
2402 const struct in6_addr *srcaddr, *dstaddr;
2403 uint16_t srcport, dstport;
2404 int len, mcast, error;
2561 if (error == 0) {
2562 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2563 if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
2564 if (mcast != 0)
2565 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
2566 } else
2567 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2568

--- 9 unchanged lines hidden (view full) ---

2578 struct mbuf *m)
2579{
2580#ifdef INET6
2581 struct ifnet *ifp;
2582 struct ip6_hdr *ip6;
2583 const struct in6_addr *srcaddr, *dstaddr;
2584 uint16_t srcport, dstport;
2585 int len, mcast, error;
2586 struct route_in6 route, *ro;
2587 struct sockaddr_in6 *sin6;
2588 uint32_t csum_flags;
2405
2589
2590 NET_EPOCH_ASSERT();
2591
2406 ifp = sc->vxl_ifp;
2407 srcaddr = &sc->vxl_src_addr.in6.sin6_addr;
2408 srcport = vxlan_pick_source_port(sc, m);
2409 dstaddr = &fvxlsa->in6.sin6_addr;
2410 dstport = fvxlsa->in6.sin6_port;
2411
2412 M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct vxlanudphdr),
2413 M_NOWAIT);

--- 10 unchanged lines hidden (view full) ---

2424 ip6->ip6_plen = 0;
2425 ip6->ip6_nxt = IPPROTO_UDP;
2426 ip6->ip6_hlim = sc->vxl_ttl;
2427 ip6->ip6_src = *srcaddr;
2428 ip6->ip6_dst = *dstaddr;
2429
2430 vxlan_encap_header(sc, m, sizeof(struct ip6_hdr), srcport, dstport);
2431
2592 ifp = sc->vxl_ifp;
2593 srcaddr = &sc->vxl_src_addr.in6.sin6_addr;
2594 srcport = vxlan_pick_source_port(sc, m);
2595 dstaddr = &fvxlsa->in6.sin6_addr;
2596 dstport = fvxlsa->in6.sin6_port;
2597
2598 M_PREPEND(m, sizeof(struct ip6_hdr) + sizeof(struct vxlanudphdr),
2599 M_NOWAIT);

--- 10 unchanged lines hidden (view full) ---

2610 ip6->ip6_plen = 0;
2611 ip6->ip6_nxt = IPPROTO_UDP;
2612 ip6->ip6_hlim = sc->vxl_ttl;
2613 ip6->ip6_src = *srcaddr;
2614 ip6->ip6_dst = *dstaddr;
2615
2616 vxlan_encap_header(sc, m, sizeof(struct ip6_hdr), srcport, dstport);
2617
2432 /*
2433 * XXX BMV We need support for RFC6935 before we can send and
2434 * receive IPv6 UDP packets with a zero checksum.
2435 */
2436 {
2618 mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
2619 m->m_flags &= ~(M_MCAST | M_BCAST);
2620
2621 ro = NULL;
2622 m->m_pkthdr.csum_flags &= CSUM_FLAGS_TX;
2623 if (m->m_pkthdr.csum_flags != 0) {
2624 /*
2625 * HW checksum (L3 and/or L4) or TSO has been requested. Look
2626 * up the ifnet for the outbound route and verify that the
2627 * outbound ifnet can perform the requested operation on the
2628 * inner frame.
2629 */
2630 bzero(&route, sizeof(route));
2631 ro = &route;
2632 sin6 = (struct sockaddr_in6 *)&ro->ro_dst;
2633 sin6->sin6_family = AF_INET6;
2634 sin6->sin6_len = sizeof(*sin6);
2635 sin6->sin6_addr = ip6->ip6_dst;
2636 ro->ro_nh = fib6_lookup(RT_DEFAULT_FIB, &ip6->ip6_dst, 0,
2637 NHR_NONE, 0);
2638 if (ro->ro_nh == NULL) {
2639 m_freem(m);
2640 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2641 return (EHOSTUNREACH);
2642 }
2643
2644 csum_flags = csum_flags_to_inner_flags(m->m_pkthdr.csum_flags,
2645 CSUM_ENCAP_VXLAN);
2646 if ((csum_flags & ro->ro_nh->nh_ifp->if_hwassist) !=
2647 csum_flags) {
2648 if (ppsratecheck(&sc->err_time, &sc->err_pps, 1)) {
2649 const struct ifnet *nh_ifp = ro->ro_nh->nh_ifp;
2650
2651 if_printf(ifp, "interface %s is missing hwcaps "
2652 "0x%08x, csum_flags 0x%08x -> 0x%08x, "
2653 "hwassist 0x%08x\n", nh_ifp->if_xname,
2654 csum_flags & ~(uint32_t)nh_ifp->if_hwassist,
2655 m->m_pkthdr.csum_flags, csum_flags,
2656 (uint32_t)nh_ifp->if_hwassist);
2657 }
2658 m_freem(m);
2659 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2660 return (ENXIO);
2661 }
2662 m->m_pkthdr.csum_flags = csum_flags;
2663 if (csum_flags &
2664 (CSUM_INNER_IP | CSUM_INNER_IP_UDP | CSUM_INNER_IP6_UDP |
2665 CSUM_INNER_IP_TCP | CSUM_INNER_IP6_TCP)) {
2666 counter_u64_add(sc->vxl_stats.txcsum, 1);
2667 if (csum_flags & CSUM_INNER_TSO)
2668 counter_u64_add(sc->vxl_stats.tso, 1);
2669 }
2670 } else if (ntohs(dstport) != V_zero_checksum_port) {
2437 struct udphdr *hdr = mtodo(m, sizeof(struct ip6_hdr));
2671 struct udphdr *hdr = mtodo(m, sizeof(struct ip6_hdr));
2672
2438 hdr->uh_sum = in6_cksum_pseudo(ip6,
2439 m->m_pkthdr.len - sizeof(struct ip6_hdr), IPPROTO_UDP, 0);
2440 m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
2441 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
2442 }
2673 hdr->uh_sum = in6_cksum_pseudo(ip6,
2674 m->m_pkthdr.len - sizeof(struct ip6_hdr), IPPROTO_UDP, 0);
2675 m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
2676 m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
2677 }
2443
2444 mcast = (m->m_flags & (M_MCAST | M_BCAST)) ? 1 : 0;
2445 m->m_flags &= ~(M_MCAST | M_BCAST);
2446
2447 error = ip6_output(m, NULL, NULL, 0, sc->vxl_im6o, NULL, NULL);
2678 error = ip6_output(m, NULL, ro, 0, sc->vxl_im6o, NULL, NULL);
2448 if (error == 0) {
2449 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2450 if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
2451 if (mcast != 0)
2452 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
2453 } else
2454 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2455

--- 132 unchanged lines hidden (view full) ---

2588 }
2589
2590 if (sc->vxl_flags & VXLAN_FLAG_LEARN)
2591 vxlan_ftable_learn(sc, sa, eh->ether_shost);
2592
2593 m_clrprotoflags(m);
2594 m->m_pkthdr.rcvif = ifp;
2595 M_SETFIB(m, ifp->if_fib);
2679 if (error == 0) {
2680 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2681 if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
2682 if (mcast != 0)
2683 if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
2684 } else
2685 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2686

--- 132 unchanged lines hidden (view full) ---

2819 }
2820
2821 if (sc->vxl_flags & VXLAN_FLAG_LEARN)
2822 vxlan_ftable_learn(sc, sa, eh->ether_shost);
2823
2824 m_clrprotoflags(m);
2825 m->m_pkthdr.rcvif = ifp;
2826 M_SETFIB(m, ifp->if_fib);
2827 if (m->m_pkthdr.csum_flags & CSUM_ENCAP_VXLAN &&
2828 ((ifp->if_capenable & IFCAP_RXCSUM &&
2829 m->m_pkthdr.csum_flags & CSUM_INNER_L3_CALC) ||
2830 (ifp->if_capenable & IFCAP_RXCSUM_IPV6 &&
2831 !(m->m_pkthdr.csum_flags & CSUM_INNER_L3_CALC)))) {
2832 uint32_t csum_flags = 0;
2596
2833
2597 error = netisr_queue_src(NETISR_ETHER, 0, m);
2834 if (m->m_pkthdr.csum_flags & CSUM_INNER_L3_CALC)
2835 csum_flags |= CSUM_L3_CALC;
2836 if (m->m_pkthdr.csum_flags & CSUM_INNER_L3_VALID)
2837 csum_flags |= CSUM_L3_VALID;
2838 if (m->m_pkthdr.csum_flags & CSUM_INNER_L4_CALC)
2839 csum_flags |= CSUM_L4_CALC;
2840 if (m->m_pkthdr.csum_flags & CSUM_INNER_L4_VALID)
2841 csum_flags |= CSUM_L4_VALID;
2842 m->m_pkthdr.csum_flags = csum_flags;
2843 counter_u64_add(sc->vxl_stats.rxcsum, 1);
2844 } else {
2845 /* clear everything */
2846 m->m_pkthdr.csum_flags = 0;
2847 m->m_pkthdr.csum_data = 0;
2848 }
2849
2850 error = netisr_dispatch(NETISR_ETHER, m);
2598 *m0 = NULL;
2599
2600out:
2601 vxlan_release(sc);
2602 return (error);
2603}
2604
2851 *m0 = NULL;
2852
2853out:
2854 vxlan_release(sc);
2855 return (error);
2856}
2857
2858static int
2859vxlan_stats_alloc(struct vxlan_softc *sc)
2860{
2861 struct vxlan_statistics *stats = &sc->vxl_stats;
2862
2863 stats->txcsum = counter_u64_alloc(M_WAITOK);
2864 if (stats->txcsum == NULL)
2865 goto failed;
2866
2867 stats->tso = counter_u64_alloc(M_WAITOK);
2868 if (stats->tso == NULL)
2869 goto failed;
2870
2871 stats->rxcsum = counter_u64_alloc(M_WAITOK);
2872 if (stats->rxcsum == NULL)
2873 goto failed;
2874
2875 return (0);
2876failed:
2877 vxlan_stats_free(sc);
2878 return (ENOMEM);
2879}
2880
2605static void
2881static void
2882vxlan_stats_free(struct vxlan_softc *sc)
2883{
2884 struct vxlan_statistics *stats = &sc->vxl_stats;
2885
2886 if (stats->txcsum != NULL) {
2887 counter_u64_free(stats->txcsum);
2888 stats->txcsum = NULL;
2889 }
2890 if (stats->tso != NULL) {
2891 counter_u64_free(stats->tso);
2892 stats->tso = NULL;
2893 }
2894 if (stats->rxcsum != NULL) {
2895 counter_u64_free(stats->rxcsum);
2896 stats->rxcsum = NULL;
2897 }
2898}
2899
2900static void
2606vxlan_set_default_config(struct vxlan_softc *sc)
2607{
2608
2609 sc->vxl_flags |= VXLAN_FLAG_LEARN;
2610
2611 sc->vxl_vni = VXLAN_VNI_MAX;
2612 sc->vxl_ttl = IPDEFTTL;
2613

--- 103 unchanged lines hidden (view full) ---

2717 if (vxlp->vxlp_learn == 0)
2718 sc->vxl_flags &= ~VXLAN_FLAG_LEARN;
2719 }
2720
2721 return (0);
2722}
2723
2724static int
2901vxlan_set_default_config(struct vxlan_softc *sc)
2902{
2903
2904 sc->vxl_flags |= VXLAN_FLAG_LEARN;
2905
2906 sc->vxl_vni = VXLAN_VNI_MAX;
2907 sc->vxl_ttl = IPDEFTTL;
2908

--- 103 unchanged lines hidden (view full) ---

3012 if (vxlp->vxlp_learn == 0)
3013 sc->vxl_flags &= ~VXLAN_FLAG_LEARN;
3014 }
3015
3016 return (0);
3017}
3018
3019static int
3020vxlan_set_reqcap(struct vxlan_softc *sc, struct ifnet *ifp, int reqcap)
3021{
3022 int mask = reqcap ^ ifp->if_capenable;
3023
3024 /* Disable TSO if tx checksums are disabled. */
3025 if (mask & IFCAP_TXCSUM && !(reqcap & IFCAP_TXCSUM) &&
3026 reqcap & IFCAP_TSO4) {
3027 reqcap &= ~IFCAP_TSO4;
3028 if_printf(ifp, "tso4 disabled due to -txcsum.\n");
3029 }
3030 if (mask & IFCAP_TXCSUM_IPV6 && !(reqcap & IFCAP_TXCSUM_IPV6) &&
3031 reqcap & IFCAP_TSO6) {
3032 reqcap &= ~IFCAP_TSO6;
3033 if_printf(ifp, "tso6 disabled due to -txcsum6.\n");
3034 }
3035
3036 /* Do not enable TSO if tx checksums are disabled. */
3037 if (mask & IFCAP_TSO4 && reqcap & IFCAP_TSO4 &&
3038 !(reqcap & IFCAP_TXCSUM)) {
3039 if_printf(ifp, "enable txcsum first.\n");
3040 return (EAGAIN);
3041 }
3042 if (mask & IFCAP_TSO6 && reqcap & IFCAP_TSO6 &&
3043 !(reqcap & IFCAP_TXCSUM_IPV6)) {
3044 if_printf(ifp, "enable txcsum6 first.\n");
3045 return (EAGAIN);
3046 }
3047
3048 sc->vxl_reqcap = reqcap;
3049 return (0);
3050}
3051
3052/*
3053 * A VXLAN interface inherits the capabilities of the vxlandev or the interface
3054 * hosting the vxlanlocal address.
3055 */
3056static void
3057vxlan_set_hwcaps(struct vxlan_softc *sc)
3058{
3059 struct epoch_tracker et;
3060 struct ifnet *p;
3061 struct ifaddr *ifa;
3062 u_long hwa;
3063 int cap, ena;
3064 bool rel;
3065 struct ifnet *ifp = sc->vxl_ifp;
3066
3067 /* reset caps */
3068 ifp->if_capabilities &= VXLAN_BASIC_IFCAPS;
3069 ifp->if_capenable &= VXLAN_BASIC_IFCAPS;
3070 ifp->if_hwassist = 0;
3071
3072 NET_EPOCH_ENTER(et);
3073 CURVNET_SET(ifp->if_vnet);
3074
3075 rel = false;
3076 p = NULL;
3077 if (sc->vxl_mc_ifname[0] != '\0') {
3078 rel = true;
3079 p = ifunit_ref(sc->vxl_mc_ifname);
3080 } else if (vxlan_sockaddr_in_any(&sc->vxl_src_addr) == 0) {
3081 if (sc->vxl_src_addr.sa.sa_family == AF_INET) {
3082 struct sockaddr_in in4 = sc->vxl_src_addr.in4;
3083
3084 in4.sin_port = 0;
3085 ifa = ifa_ifwithaddr((struct sockaddr *)&in4);
3086 if (ifa != NULL)
3087 p = ifa->ifa_ifp;
3088 } else if (sc->vxl_src_addr.sa.sa_family == AF_INET6) {
3089 struct sockaddr_in6 in6 = sc->vxl_src_addr.in6;
3090
3091 in6.sin6_port = 0;
3092 ifa = ifa_ifwithaddr((struct sockaddr *)&in6);
3093 if (ifa != NULL)
3094 p = ifa->ifa_ifp;
3095 }
3096 }
3097 if (p == NULL)
3098 goto done;
3099
3100 cap = ena = hwa = 0;
3101
3102 /* checksum offload */
3103 if (p->if_capabilities & IFCAP_VXLAN_HWCSUM)
3104 cap |= p->if_capabilities & (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6);
3105 if (p->if_capenable & IFCAP_VXLAN_HWCSUM) {
3106 ena |= sc->vxl_reqcap & p->if_capenable &
3107 (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6);
3108 if (ena & IFCAP_TXCSUM) {
3109 if (p->if_hwassist & CSUM_INNER_IP)
3110 hwa |= CSUM_IP;
3111 if (p->if_hwassist & CSUM_INNER_IP_UDP)
3112 hwa |= CSUM_IP_UDP;
3113 if (p->if_hwassist & CSUM_INNER_IP_TCP)
3114 hwa |= CSUM_IP_TCP;
3115 }
3116 if (ena & IFCAP_TXCSUM_IPV6) {
3117 if (p->if_hwassist & CSUM_INNER_IP6_UDP)
3118 hwa |= CSUM_IP6_UDP;
3119 if (p->if_hwassist & CSUM_INNER_IP6_TCP)
3120 hwa |= CSUM_IP6_TCP;
3121 }
3122 }
3123
3124 /* hardware TSO */
3125 if (p->if_capabilities & IFCAP_VXLAN_HWTSO) {
3126 cap |= p->if_capabilities & IFCAP_TSO;
3127 if (p->if_hw_tsomax > IP_MAXPACKET - ifp->if_hdrlen)
3128 ifp->if_hw_tsomax = IP_MAXPACKET - ifp->if_hdrlen;
3129 else
3130 ifp->if_hw_tsomax = p->if_hw_tsomax;
3131 /* XXX: tsomaxsegcount decrement is cxgbe specific */
3132 ifp->if_hw_tsomaxsegcount = p->if_hw_tsomaxsegcount - 1;
3133 ifp->if_hw_tsomaxsegsize = p->if_hw_tsomaxsegsize;
3134 }
3135 if (p->if_capenable & IFCAP_VXLAN_HWTSO) {
3136 ena |= sc->vxl_reqcap & p->if_capenable & IFCAP_TSO;
3137 if (ena & IFCAP_TSO) {
3138 if (p->if_hwassist & CSUM_INNER_IP_TSO)
3139 hwa |= CSUM_IP_TSO;
3140 if (p->if_hwassist & CSUM_INNER_IP6_TSO)
3141 hwa |= CSUM_IP6_TSO;
3142 }
3143 }
3144
3145 ifp->if_capabilities |= cap;
3146 ifp->if_capenable |= ena;
3147 ifp->if_hwassist |= hwa;
3148 if (rel)
3149 if_rele(p);
3150done:
3151 CURVNET_RESTORE();
3152 NET_EPOCH_EXIT(et);
3153}
3154
3155static int
2725vxlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
2726{
2727 struct vxlan_softc *sc;
2728 struct ifnet *ifp;
2729 struct ifvxlanparam vxlp;
2730 int error;
2731
2732 sc = malloc(sizeof(struct vxlan_softc), M_VXLAN, M_WAITOK | M_ZERO);
2733 sc->vxl_unit = unit;
2734 vxlan_set_default_config(sc);
3156vxlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
3157{
3158 struct vxlan_softc *sc;
3159 struct ifnet *ifp;
3160 struct ifvxlanparam vxlp;
3161 int error;
3162
3163 sc = malloc(sizeof(struct vxlan_softc), M_VXLAN, M_WAITOK | M_ZERO);
3164 sc->vxl_unit = unit;
3165 vxlan_set_default_config(sc);
3166 error = vxlan_stats_alloc(sc);
3167 if (error != 0)
3168 goto fail;
2735
2736 if (params != 0) {
2737 error = copyin(params, &vxlp, sizeof(vxlp));
2738 if (error)
2739 goto fail;
2740
2741 error = vxlan_set_user_config(sc, &vxlp);
2742 if (error)

--- 16 unchanged lines hidden (view full) ---

2759
2760 ifp->if_softc = sc;
2761 if_initname(ifp, vxlan_name, unit);
2762 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
2763 ifp->if_init = vxlan_init;
2764 ifp->if_ioctl = vxlan_ioctl;
2765 ifp->if_transmit = vxlan_transmit;
2766 ifp->if_qflush = vxlan_qflush;
3169
3170 if (params != 0) {
3171 error = copyin(params, &vxlp, sizeof(vxlp));
3172 if (error)
3173 goto fail;
3174
3175 error = vxlan_set_user_config(sc, &vxlp);
3176 if (error)

--- 16 unchanged lines hidden (view full) ---

3193
3194 ifp->if_softc = sc;
3195 if_initname(ifp, vxlan_name, unit);
3196 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
3197 ifp->if_init = vxlan_init;
3198 ifp->if_ioctl = vxlan_ioctl;
3199 ifp->if_transmit = vxlan_transmit;
3200 ifp->if_qflush = vxlan_qflush;
2767 ifp->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
2768 ifp->if_capenable |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
3201 ifp->if_capabilities = VXLAN_BASIC_IFCAPS;
3202 ifp->if_capenable = VXLAN_BASIC_IFCAPS;
3203 sc->vxl_reqcap = -1;
3204 vxlan_set_hwcaps(sc);
2769
2770 ifmedia_init(&sc->vxl_media, 0, vxlan_media_change, vxlan_media_status);
2771 ifmedia_add(&sc->vxl_media, IFM_ETHER | IFM_AUTO, 0, NULL);
2772 ifmedia_set(&sc->vxl_media, IFM_ETHER | IFM_AUTO);
2773
2774 ether_gen_addr(ifp, &sc->vxl_hwaddr);
2775 ether_ifattach(ifp, sc->vxl_hwaddr.octet);
2776
2777 ifp->if_baudrate = 0;
3205
3206 ifmedia_init(&sc->vxl_media, 0, vxlan_media_change, vxlan_media_status);
3207 ifmedia_add(&sc->vxl_media, IFM_ETHER | IFM_AUTO, 0, NULL);
3208 ifmedia_set(&sc->vxl_media, IFM_ETHER | IFM_AUTO);
3209
3210 ether_gen_addr(ifp, &sc->vxl_hwaddr);
3211 ether_ifattach(ifp, sc->vxl_hwaddr.octet);
3212
3213 ifp->if_baudrate = 0;
2778 ifp->if_hdrlen = 0;
3214 vxlan_setup_interface_hdrlen(sc);
2779
2780 return (0);
2781
2782fail:
2783 free(sc, M_VXLAN);
2784 return (error);
2785}
2786

--- 11 unchanged lines hidden (view full) ---

2798 ether_ifdetach(ifp);
2799 if_free(ifp);
2800 ifmedia_removeall(&sc->vxl_media);
2801
2802 vxlan_ftable_fini(sc);
2803
2804 vxlan_sysctl_destroy(sc);
2805 rm_destroy(&sc->vxl_lock);
3215
3216 return (0);
3217
3218fail:
3219 free(sc, M_VXLAN);
3220 return (error);
3221}
3222

--- 11 unchanged lines hidden (view full) ---

3234 ether_ifdetach(ifp);
3235 if_free(ifp);
3236 ifmedia_removeall(&sc->vxl_media);
3237
3238 vxlan_ftable_fini(sc);
3239
3240 vxlan_sysctl_destroy(sc);
3241 rm_destroy(&sc->vxl_lock);
3242 vxlan_stats_free(sc);
2806 free(sc, M_VXLAN);
2807}
2808
2809/* BMV: Taken from if_bridge. */
2810static uint32_t
2811vxlan_mac_hash(struct vxlan_softc *sc, const uint8_t *addr)
2812{
2813 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->vxl_ftable_hash_key;

--- 268 unchanged lines hidden (view full) ---

3082 OID_AUTO, "stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
3083 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
3084 "ftable_nospace", CTLFLAG_RD, &stats->ftable_nospace, 0,
3085 "Fowarding table reached maximum entries");
3086 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
3087 "ftable_lock_upgrade_failed", CTLFLAG_RD,
3088 &stats->ftable_lock_upgrade_failed, 0,
3089 "Forwarding table update required lock upgrade");
3243 free(sc, M_VXLAN);
3244}
3245
3246/* BMV: Taken from if_bridge. */
3247static uint32_t
3248vxlan_mac_hash(struct vxlan_softc *sc, const uint8_t *addr)
3249{
3250 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->vxl_ftable_hash_key;

--- 268 unchanged lines hidden (view full) ---

3519 OID_AUTO, "stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "");
3520 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
3521 "ftable_nospace", CTLFLAG_RD, &stats->ftable_nospace, 0,
3522 "Fowarding table reached maximum entries");
3523 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
3524 "ftable_lock_upgrade_failed", CTLFLAG_RD,
3525 &stats->ftable_lock_upgrade_failed, 0,
3526 "Forwarding table update required lock upgrade");
3527
3528 SYSCTL_ADD_COUNTER_U64(ctx, SYSCTL_CHILDREN(node), OID_AUTO, "txcsum",
3529 CTLFLAG_RD, &stats->txcsum,
3530 "# of times hardware assisted with tx checksum");
3531 SYSCTL_ADD_COUNTER_U64(ctx, SYSCTL_CHILDREN(node), OID_AUTO, "tso",
3532 CTLFLAG_RD, &stats->tso, "# of times hardware assisted with TSO");
3533 SYSCTL_ADD_COUNTER_U64(ctx, SYSCTL_CHILDREN(node), OID_AUTO, "rxcsum",
3534 CTLFLAG_RD, &stats->rxcsum,
3535 "# of times hardware assisted with rx checksum");
3090}
3091
3092static void
3093vxlan_sysctl_destroy(struct vxlan_softc *sc)
3094{
3095
3096 sysctl_ctx_free(&sc->vxl_sysctl_ctx);
3097 sc->vxl_sysctl_node = NULL;

--- 28 unchanged lines hidden (view full) ---

3126 VXLAN_LIST_LOCK();
3127 LIST_FOREACH(vso, &vxlan_socket_list, vxlso_entry)
3128 vxlan_socket_ifdetach(vso, ifp, &list);
3129 VXLAN_LIST_UNLOCK();
3130
3131 LIST_FOREACH_SAFE(sc, &list, vxl_ifdetach_list, tsc) {
3132 LIST_REMOVE(sc, vxl_ifdetach_list);
3133
3536}
3537
3538static void
3539vxlan_sysctl_destroy(struct vxlan_softc *sc)
3540{
3541
3542 sysctl_ctx_free(&sc->vxl_sysctl_ctx);
3543 sc->vxl_sysctl_node = NULL;

--- 28 unchanged lines hidden (view full) ---

3572 VXLAN_LIST_LOCK();
3573 LIST_FOREACH(vso, &vxlan_socket_list, vxlso_entry)
3574 vxlan_socket_ifdetach(vso, ifp, &list);
3575 VXLAN_LIST_UNLOCK();
3576
3577 LIST_FOREACH_SAFE(sc, &list, vxl_ifdetach_list, tsc) {
3578 LIST_REMOVE(sc, vxl_ifdetach_list);
3579
3580 sx_xlock(&vxlan_sx);
3134 VXLAN_WLOCK(sc);
3135 if (sc->vxl_flags & VXLAN_FLAG_INIT)
3136 vxlan_init_wait(sc);
3137 vxlan_teardown_locked(sc);
3581 VXLAN_WLOCK(sc);
3582 if (sc->vxl_flags & VXLAN_FLAG_INIT)
3583 vxlan_init_wait(sc);
3584 vxlan_teardown_locked(sc);
3585 sx_xunlock(&vxlan_sx);
3138 }
3139}
3140
3141static void
3142vxlan_load(void)
3143{
3144
3145 mtx_init(&vxlan_list_mtx, "vxlan list", NULL, MTX_DEF);

--- 48 unchanged lines hidden ---
3586 }
3587}
3588
3589static void
3590vxlan_load(void)
3591{
3592
3593 mtx_init(&vxlan_list_mtx, "vxlan list", NULL, MTX_DEF);

--- 48 unchanged lines hidden ---