Fix issues when handling unkown ipv6 packets
[samplevnf.git] / VNFs / DPPD-PROX / handle_master.c
index 3be5581..169c7ca 100644 (file)
@@ -167,16 +167,17 @@ void master_init_vdev(struct task_base *tbase, uint8_t port_id, uint8_t core_id,
 
                struct sockaddr_in dst, src;
                src.sin_family = AF_INET;
-               src.sin_addr.s_addr = prox_port_cfg[vdev_port].ip;
                src.sin_port = rte_cpu_to_be_16(PROX_PSEUDO_PKT_PORT);
-
-               int fd = socket(AF_INET,  SOCK_DGRAM, 0);
-               PROX_PANIC(fd < 0, "Failed to open socket(AF_INET,  SOCK_DGRAM, 0)\n");
-               prox_port_cfg[vdev_port].fd = fd;
-               rc = bind(fd,(struct sockaddr *)&src, sizeof(struct sockaddr_in));
-               PROX_PANIC(rc, "Failed to bind("IPv4_BYTES_FMT":%d): errno = %d (%s)\n", IPv4_BYTES(((uint8_t*)&src.sin_addr.s_addr)), src.sin_port, errno, strerror(errno));
-               plog_info("DPDK port %d bound("IPv4_BYTES_FMT":%d) to fd %d\n", port_id, IPv4_BYTES(((uint8_t*)&src.sin_addr.s_addr)), src.sin_port, fd);
-               fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+               for (int vlan_id = 0; vlan_id < prox_port_cfg[vdev_port].n_vlans; vlan_id++) {
+                       src.sin_addr.s_addr = rte_be_to_cpu_32(prox_port_cfg[vdev_port].ip_addr[vlan_id].ip);
+                       int fd = socket(AF_INET,  SOCK_DGRAM, 0);
+                       PROX_PANIC(fd < 0, "Failed to open socket(AF_INET,  SOCK_DGRAM, 0)\n");
+                       prox_port_cfg[vdev_port].fds[vlan_id] = fd;
+                       rc = bind(fd,(struct sockaddr *)&src, sizeof(struct sockaddr_in));
+                       PROX_PANIC(rc, "Failed to bind("IPv4_BYTES_FMT":%d): errno = %d (%s)\n", IPv4_BYTES(((uint8_t*)&src.sin_addr.s_addr)), src.sin_port, errno, strerror(errno));
+                       plog_info("DPDK port %d bound("IPv4_BYTES_FMT":%d) to fd %d\n", port_id, IPv4_BYTES(((uint8_t*)&src.sin_addr.s_addr)), src.sin_port, fd);
+                       fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+               }
                task->max_vdev_id++;
        }
 }
@@ -375,7 +376,7 @@ static inline void build_icmp_reply_message(struct task_base *tbase, struct rte_
 static inline void handle_icmp(struct task_base *tbase, struct rte_mbuf *mbuf)
 {
        struct task_master *task = (struct task_master *)tbase;
-       uint8_t port_id = mbuf->port;
+       uint8_t port_id = get_port(mbuf);
        struct port_table *port = &task->internal_port_table[port_id];
        prox_rte_ether_hdr *hdr = rte_pktmbuf_mtod(mbuf, prox_rte_ether_hdr *);
        if (hdr->ether_type != ETYPE_IPv4) {
@@ -401,7 +402,7 @@ static inline void handle_icmp(struct task_base *tbase, struct rte_mbuf *mbuf)
                        port->n_echo_req = 0;
                        port->last_echo_req_rcvd_tsc = rte_rdtsc();
                }
-               build_icmp_reply_message(tbase, mbuf);
+               return build_icmp_reply_message(tbase, mbuf);
        } else if (type == PROX_RTE_IP_ICMP_ECHO_REPLY) {
                port->n_echo_rep++;
                if (rte_rdtsc() - port->last_echo_rep_rcvd_tsc > rte_get_tsc_hz()) {
@@ -418,21 +419,21 @@ static inline void handle_unknown_ip6(struct task_base *tbase, struct rte_mbuf *
 {
        struct task_master *task = (struct task_master *)tbase;
        struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
-       uint8_t port = get_port(mbuf);
+       uint8_t port_id = get_port(mbuf);
        struct ipv6_addr *ip_dst = ctrl_ring_get_ipv6_addr(mbuf);
        uint16_t vlan = ctrl_ring_get_vlan(mbuf);
        int ret1, ret2, i;
 
-       plogx_dbg("\tMaster trying to find MAC of external IP "IPv6_BYTES_FMT" for port %d\n", IPv6_BYTES(ip_dst->bytes), port);
-       if (unlikely(port >= PROX_MAX_PORTS)) {
-               plogx_dbg("Port %d not found", port);
+       plogx_dbg("\tMaster trying to find MAC of external IP "IPv6_BYTES_FMT" for port %d\n", IPv6_BYTES(ip_dst->bytes), port_id);
+       if (unlikely(port_id >= PROX_MAX_PORTS)) {
+               plogx_dbg("Port %d not found", port_id);
                tx_drop(mbuf);
                return;
        }
-       struct ipv6_addr *local_ip_src = &task->internal_port_table[port].local_ipv6_addr;
-       struct ipv6_addr *global_ip_src = &task->internal_port_table[port].global_ipv6_addr;
+       struct ipv6_addr *local_ip_src = &task->internal_port_table[port_id].local_ipv6_addr;
+       struct ipv6_addr *global_ip_src = &task->internal_port_table[port_id].global_ipv6_addr;
        struct ipv6_addr *ip_src;
-       if (memcmp(local_ip_src, ip_dst, 8) == 0)
+       if (memcmp(local_ip_src, ip_dst, prox_port_cfg[port_id].v6_mask_length) == 0)
                ip_src = local_ip_src;
        else if (memcmp(global_ip_src,  &null_addr, 16))
                ip_src = global_ip_src;
@@ -444,7 +445,7 @@ static inline void handle_unknown_ip6(struct task_base *tbase, struct rte_mbuf *
        struct rte_ring *ring = task->ctrl_tx_rings[get_core(mbuf) * MAX_TASKS_PER_CORE + get_task(mbuf)];
 
        if (ring == NULL) {
-               plogx_dbg("Port %d not registered", port);
+               plogx_dbg("Port %d not registered", port_id);
                tx_drop(mbuf);
                return;
        }
@@ -475,12 +476,12 @@ static inline void handle_unknown_ip6(struct task_base *tbase, struct rte_mbuf *
                task->external_ip6_table[ret2].nb_requests++;
                // Only needed for first request - but avoid test and copy the same 6 bytes
                // In most cases we will only have one request per IP.
-               //memcpy(&task->external_ip6_table[ret2].mac, &task->internal_port_table[port].mac, sizeof(prox_rte_ether_addr));
+               //memcpy(&task->external_ip6_table[ret2].mac, &task->internal_port_table[port_id].mac, sizeof(prox_rte_ether_addr));
        }
 
        // As timers are not handled by master, we might send an NS request even if one was just sent
        // (and not yet answered) by another task
-       build_neighbour_sollicitation(mbuf, &task->internal_port_table[port].mac, ip_dst, ip_src, vlan);
+       build_neighbour_sollicitation(mbuf, &task->internal_port_table[port_id].mac, ip_dst, ip_src, vlan);
        tx_ring(tbase, ring, SEND_NDP_FROM_MASTER, mbuf);
 }
 
@@ -624,6 +625,7 @@ static inline void handle_ns(struct task_base *tbase, struct rte_mbuf *mbuf, pro
                tx_drop(mbuf);
        } else {
                struct rte_ring *ring = task->internal_ip6_table[ret].ring;
+               if (ring == NULL) return;
                build_neighbour_advertisement(tbase, mbuf, &task->internal_ip6_table[ret].mac, &key.ip6, PROX_SOLLICITED, vlan);
                tx_ring(tbase, ring, SEND_NDP_FROM_MASTER, mbuf);
        }
@@ -674,7 +676,7 @@ static inline void handle_na(struct task_base *tbase, struct rte_mbuf *mbuf, pro
        }
 
        if (target_address == NULL) {
-               tx_drop(mbuf);
+               target_address = (uint8_t *)&neighbour_advertisement->destination_address;
        }
        struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
        struct ipv6_addr *key = &neighbour_advertisement->destination_address;
@@ -682,6 +684,7 @@ static inline void handle_na(struct task_base *tbase, struct rte_mbuf *mbuf, pro
        ret = rte_hash_lookup(task->external_ip6_hash, (const void *)key);
        if (unlikely(ret < 0)) {
                // entry not found for this IP: we did not ask a request, delete the reply
+               plog_err("Unkown IP "IPv6_BYTES_FMT"", IPv6_BYTES(neighbour_advertisement->destination_address.bytes));
                tx_drop(mbuf);
        } else {
                // entry found for this IP
@@ -696,6 +699,7 @@ static inline void handle_na(struct task_base *tbase, struct rte_mbuf *mbuf, pro
                        }
                        task->external_ip6_table[ret].nb_requests = 0;
                } else {
+                       plog_err("UNEXPECTED nb_requests == 0");
                        tx_drop(mbuf);
                }
        }
@@ -783,6 +787,7 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
 
                        struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *);
                        uint32_t ip = get_ip(mbuf);
+                       vlan = ctrl_ring_get_vlan(mbuf);
                        struct rte_ring *ring = task->ctrl_tx_rings[get_core(mbuf) * MAX_TASKS_PER_CORE + get_task(mbuf)];
 
                        // First check whether MAC address is not already in kernel MAC table.
@@ -803,12 +808,23 @@ static inline void handle_message(struct task_base *tbase, struct rte_mbuf *mbuf
                        dst.sin_family = AF_INET;
                        dst.sin_addr.s_addr = ip;
                        dst.sin_port = rte_cpu_to_be_16(PROX_PSEUDO_PKT_PORT);
-                       // TODO VLAN: find the right fd based on the VLAN
-                       int n = sendto(prox_port_cfg[vdev_port].fd, (char*)(&ip), 0, MSG_DONTROUTE,  (struct sockaddr *)&dst, sizeof(struct sockaddr_in));
+
+                       int vlan_id;
+                       for (vlan_id = 0; vlan_id < prox_port_cfg[vdev_port].n_vlans; vlan_id++) {
+                               if (prox_port_cfg[vdev_port].vlan_tags[vlan_id] == vlan)
+                                       break;
+                       }
+                       if (vlan_id >= prox_port_cfg[vdev_port].n_vlans) {
+                               // Tag not found
+                               plogx_info("\tDid not send to TAP IP "IPv4_BYTES_FMT" as wrong VLAN %d\n", IPv4_BYTES(((uint8_t*)&ip)), vlan);
+                               tx_drop(mbuf);
+                               break;
+                       }
+                       int n = sendto(prox_port_cfg[vdev_port].fds[vlan_id], (char*)(&ip), 0, MSG_DONTROUTE,  (struct sockaddr *)&dst, sizeof(struct sockaddr_in));
                        if (n < 0) {
-                               plogx_info("\tFailed to send to TAP IP "IPv4_BYTES_FMT" using fd %d, error = %d (%s)\n", IPv4_BYTES(((uint8_t*)&ip)), prox_port_cfg[vdev_port].fd, errno, strerror(errno));
+                               plogx_info("\tFailed to send to TAP IP "IPv4_BYTES_FMT" using fd %d, error = %d (%s)\n", IPv4_BYTES(((uint8_t*)&ip)), prox_port_cfg[vdev_port].fds[vlan_id], errno, strerror(errno));
                        } else
-                               plogx_dbg("\tSent %d bytes to TAP IP "IPv4_BYTES_FMT" using fd %d\n", n, IPv4_BYTES(((uint8_t*)&ip)), prox_port_cfg[vdev_port].fd);
+                               plogx_dbg("\tSent %d bytes to TAP IP "IPv4_BYTES_FMT" using fd %d\n", n, IPv4_BYTES(((uint8_t*)&ip)), prox_port_cfg[vdev_port].fds[vlan_id]);
 
                        record_request(tbase, ip, port, ring);
                        tx_drop(mbuf);
@@ -956,7 +972,7 @@ void init_ctrl_plane(struct task_base *tbase)
        struct sockaddr_nl sockaddr2;
        memset(&sockaddr2, 0, sizeof(struct sockaddr_nl));
        sockaddr2.nl_family = AF_NETLINK;
-       sockaddr2.nl_groups = RTMGRP_IPV6_ROUTE | RTMGRP_IPV4_ROUTE | RTMGRP_NOTIFY;
+       sockaddr2.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_NOTIFY;
        rc = bind(fd, (struct sockaddr *)&sockaddr2, sizeof(struct sockaddr_nl));
        PROX_PANIC(rc < 0, "Failed to bind to RTMGRP_NEIGH netlink group\n");
        task->route_fds.fd = fd;
@@ -999,7 +1015,11 @@ static void handle_route_event(struct task_base *tbase)
 
        struct rtmsg *rtmsg = (struct rtmsg *)NLMSG_DATA(nl_hdr);
        int rtm_family = rtmsg->rtm_family;
-       if ((rtm_family == AF_INET) && (rtmsg->rtm_table != RT_TABLE_MAIN) &&(rtmsg->rtm_table != RT_TABLE_LOCAL))
+       if (rtm_family != AF_INET) {
+               plog_warn("Unhandled non IPV4 routing message\n");
+               return;
+       }
+       if ((rtmsg->rtm_table != RT_TABLE_MAIN) && (rtmsg->rtm_table != RT_TABLE_LOCAL))
                return;
        int dst_len = rtmsg->rtm_dst_len;
 
@@ -1028,8 +1048,14 @@ static void handle_route_event(struct task_base *tbase)
        }
        int dpdk_vdev_port = -1;
        for (int i = 0; i< prox_rte_eth_dev_count_avail(); i++) {
-               if (strcmp(prox_port_cfg[i].name, interface_name) == 0)
-                       dpdk_vdev_port = i;
+               for (int vlan_id = 0; vlan_id < prox_port_cfg[i].n_vlans; vlan_id++) {
+                       if (strcmp(prox_port_cfg[i].names[vlan_id], interface_name) == 0) {
+                               dpdk_vdev_port = i;
+                               break;
+                       }
+               }
+               if (dpdk_vdev_port != -1)
+                       break;
        }
        if (dpdk_vdev_port != -1) {
                plogx_info("Received netlink message on tap interface %s for IP "IPv4_BYTES_FMT"/%d, Gateway  "IPv4_BYTES_FMT"\n", interface_name, IP4(ip), dst_len, IP4(gw_ip));