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 --- |