Procházet zdrojové kódy

esp-netif: Added API to get the underlying interface name

The interface name can be used in socket API, i.e. setsockopt(). The API esp_netif_get_netif_impl_name() shoudl be used to populate standard
interface structure struct ifreq.
David Cermak před 5 roky
rodič
revize
8a45f074fc

+ 16 - 0
components/esp_netif/include/esp_netif.h

@@ -402,6 +402,22 @@ esp_err_t esp_netif_set_old_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_i
  */
 int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif);
 
+/**
+ * @brief  Get net interface name from network stack implementation
+ *
+ * @note This name could be used in `setsockopt()` to bind socket with appropriate interface
+ *
+ * @param[in]  esp_netif Handle to esp-netif instance
+ * @param[out]  name Interface name as specified in underlying TCP/IP stack. Note that the
+ * actual name will be copied to the specified buffer, which must be allocated to hold
+ * maximum interface name size (6 characters for lwIP)
+ *
+ * @return
+ *         - ESP_OK
+ *         - ESP_ERR_ESP_NETIF_INVALID_PARAMS
+*/
+esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name);
+
 /**
  * @}
  */

+ 11 - 0
components/esp_netif/lwip/esp_netif_lwip.c

@@ -1736,4 +1736,15 @@ int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
     return netif_get_index(esp_netif->lwip_netif);
 }
 
+esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
+{
+    ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
+
+    if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
+        return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
+    }
+    netif_index_to_name(netif_get_index(esp_netif->lwip_netif), name);
+    return ESP_OK;
+}
+
 #endif /* CONFIG_ESP_NETIF_TCPIP_LWIP */

+ 8 - 0
examples/protocols/sockets/tcp_client_multi_net/main/Kconfig.projbuild

@@ -13,4 +13,12 @@ menu "Example Configuration"
         help
             host port
 
+    config EXAMPLE_BIND_SOCKET_TO_NETIF_NAME
+        bool "Bind to interface by its name"
+        default y
+        help
+            By default example uses setsockopt() to bind the tcp-client's socket
+            to specific interface. Setting this option to true demonstrates binding
+            the socket to the local ip address of the network interface.
+
 endmenu

+ 16 - 3
examples/protocols/sockets/tcp_client_multi_net/main/tcp_client_multiple.c

@@ -30,7 +30,6 @@ static const char *payload = "GET / HTTP/1.1\r\n\r\n";
 
 static void app_multiple_handle(esp_ip4_addr_t *ip4_addr, esp_netif_t *esp_netif)
 {
-    esp_netif_ip_info_t ip;
     char rx_buffer[128] = {0};
     const char *netif_name = esp_netif_get_desc(esp_netif);
 
@@ -42,7 +41,20 @@ static void app_multiple_handle(esp_ip4_addr_t *ip4_addr, esp_netif_t *esp_netif
     }
     ESP_LOGI(TAG, "\"%s\" Socket created", netif_name);
 
-    /* Bind local IP of the network interface */
+    /* Bind the socket to an interface (based on example config option)
+     * - using netif local IP address
+     * - using netif name
+     */
+#if CONFIG_EXAMPLE_BIND_SOCKET_TO_NETIF_NAME
+    struct ifreq ifr;
+    esp_netif_get_netif_impl_name(esp_netif, ifr.ifr_name);
+    int ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,  (void*)&ifr, sizeof(struct ifreq));
+    if (ret < 0) {
+        ESP_LOGE(TAG, "\"%s\" Unable to bind socket to specified interface: errno %d", netif_name, errno);
+        goto app_multiple_handle_fail;
+    }
+#else
+    esp_netif_ip_info_t ip;
     memset(&ip, 0, sizeof(esp_netif_ip_info_t));
     ESP_ERROR_CHECK(esp_netif_get_ip_info(esp_netif, &ip));
 
@@ -51,12 +63,13 @@ static void app_multiple_handle(esp_ip4_addr_t *ip4_addr, esp_netif_t *esp_netif
     addr.sin_family = AF_INET;
     addr.sin_port = htons(0);
     addr.sin_addr.s_addr = ip.ip.addr;
-            
+
     int ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
     if (ret < 0) {
         ESP_LOGE(TAG, "\"%s\" Unable to bind socket: errno %d", netif_name, errno);
         goto app_multiple_handle_fail;
     }
+#endif /* CONFIG_EXAMPLE_BIND_SOCKET_TO_NETIF_NAME */
 
     /* Connect to the host by the network interface */
     struct sockaddr_in destAddr;