示例#1
0
int ofp_term_global(void)
{
	int rc = 0;
	uint16_t i;
	struct ofp_ifnet *ifnet;

	ofp_stop();

	/* Terminate CLI thread*/
	CHECK_ERROR(ofp_stop_cli_thread(), rc);

#ifdef SP
	/* Terminate Netlink thread*/
	if (shm->nl_thread_is_running) {
		odph_linux_pthread_join(&shm->nl_thread, 1);
		shm->nl_thread_is_running = 0;
	}
#endif /* SP */

	/* Cleanup interfaces: queues and pktios*/
	for (i = 0; i < VXLAN_PORTS; i++) {
		ifnet = ofp_get_ifnet((uint16_t)i, 0);
		if (!ifnet) {
			OFP_ERR("Failed to locate interface for port %d", i);
			rc = -1;
			continue;
		}
		if (ifnet->if_state == OFP_IFT_STATE_FREE)
			continue;

		if (ifnet->pktio == ODP_PKTIO_INVALID)
			continue;

		OFP_INFO("Cleaning device '%s' addr %s", ifnet->if_name,
			ofp_print_mac((uint8_t *)ifnet->mac));

		CHECK_ERROR(odp_pktio_stop(ifnet->pktio), rc);
#ifdef SP
		close(ifnet->fd);
		odph_linux_pthread_join(ifnet->rx_tbl, 1);
		odph_linux_pthread_join(ifnet->tx_tbl, 1);
		ifnet->fd = -1;
#endif /*SP*/

		/* Multicasting. */
		ofp_igmp_domifdetach(ifnet);
		ifnet->ii_inet.ii_igmp = NULL;

		if (ifnet->loopq_def != ODP_QUEUE_INVALID) {
			if (odp_queue_destroy(ifnet->loopq_def) < 0) {
				OFP_ERR("Failed to destroy loop queue for %s",
					ifnet->if_name);
				rc = -1;
			}
			ifnet->loopq_def = ODP_QUEUE_INVALID;
		}
#ifdef SP
		if (ifnet->spq_def != ODP_QUEUE_INVALID) {
			cleanup_pkt_queue(ifnet->spq_def);
			if (odp_queue_destroy(ifnet->spq_def) < 0) {
				OFP_ERR("Failed to destroy slow path "
					"queue for %s", ifnet->if_name);
				rc = -1;
			}
			ifnet->spq_def = ODP_QUEUE_INVALID;
		}
#endif /*SP*/
		ifnet->outq_def = ODP_QUEUE_INVALID;

		if (ifnet->pktio != ODP_PKTIO_INVALID) {
			if (odp_pktio_close(ifnet->pktio) < 0) {
				OFP_ERR("Failed to destroy pktio for %s",
					ifnet->if_name);
				rc = -1;
			}
			ifnet->pktio = ODP_PKTIO_INVALID;
		}

		if (ifnet->inq_def != ODP_QUEUE_INVALID) {
			cleanup_pkt_queue(ifnet->inq_def);
			if (odp_queue_destroy(ifnet->inq_def) < 0) {
				OFP_ERR("Failed to destroy default input "
					"queue for %s", ifnet->if_name);
				rc = -1;
			}
			ifnet->inq_def = ODP_QUEUE_INVALID;
		}
	}

	CHECK_ERROR(ofp_clean_vxlan_interface_queue(), rc);

	if (ofp_term_post_global(SHM_PACKET_POOL_NAME)) {
		OFP_ERR("Failed to cleanup resources\n");
		rc = -1;
	}

	return rc;
}
示例#2
0
/* for local debug */
void ofp_print_packet_buffer(const char *comment, uint8_t *p)
{
	static int first = 1;
	FILE *f;
	struct ofp_ip *ip;
	uint16_t proto;
	char *g;

/*
 * Filter "noise"
 */
#if 0
	if (p[12] == 0x00 && p[13] == 0x27)
		return;
	if (p[12] == 0x01 && p[13] == 0x98)
		return;
#endif
	if (first) {
		f = fopen(DEFAULT_DEBUG_TXT_FILE_NAME, "w");
		fclose(f);
		first = 0;
	}

	f = fopen(DEFAULT_DEBUG_TXT_FILE_NAME, "a");

	if (!f)
		return;

	static struct timeval tv0;
	struct timeval tv;

	gettimeofday(&tv, NULL);
	if (tv0.tv_sec == 0)
		tv0 = tv;
	int ms = (tv.tv_sec*1000+tv.tv_usec/1000) -
		(tv0.tv_sec*1000+tv0.tv_usec/1000);

	ofp_printf(f, "\n*************\n");
	ofp_printf(f, "[%d] %s: %d.%03d\n", odp_cpu_id(), comment,
		       ms/1000, ms%1000);
	ofp_printf(f, "%s ->%s\n  ", ofp_print_mac(p+6), ofp_print_mac(p));

	if (p[12] == 0x81 && p[13] == 0x00) {
		ofp_printf(f, "VLAN %d ", (p[14]<<8)|p[15]);
		p += 4;
	}

	if (p[12] == 0x88 && p[13] == 0x47) {
		uint8_t *label = p+14;
		int i;

		ofp_printf(f, "MPLS ");
		while (1) {
			ofp_printf(f, "[label=%d ttl=%d] ",
				label[0]*16*256 + label[1]*16 + label[2]/16,
				label[3]);
			if (label[2] & 1)
				break;
			label += 4;
		}

		if ((label[4] & 0xf0) == 0x40) {
			label[2] = 0x08; /* ipv4 */
			label[3] = 0x00;
		} else {
			label[2] = 0x86; /* ipv6 */
			label[3] = 0xdd;
		}

		label++;
		for (i = 0; i < 12; i++)
			*label-- = p[11 - i];
		p = label+1;
	}

	if (p[12] == 0x08 && p[13] == 0x06) {
		print_arp(f, (char *)(p + L2_HEADER_NO_VLAN_SIZE));
	} else if (p[12] == 0x86 && p[13] == 0xdd) {
		print_ipv6(f, (char *)(p + L2_HEADER_NO_VLAN_SIZE));
	} else if (p[12] == 0x08 && p[13] == 0x00) {
		ip = (struct ofp_ip *)(p + L2_HEADER_NO_VLAN_SIZE);

		if (ip->ip_p == 47) { /* GRE */
			g = ((char *)ip) + (ip->ip_hl << 2);
			g += print_gre(f, g, &proto);
			if (proto == 0x0800)
				print_ipv4(f, g);
			else if (proto == 0x86dd)
				print_ipv6(f, g);
		} else
			print_ipv4(f, (char *)(p + L2_HEADER_NO_VLAN_SIZE));
	} else {
		ofp_printf(f, "UNKNOWN ETH PACKET TYPE 0x%02x%02x ",
			p[12], p[13]);
	}

	ofp_printf(f, "\n");
	fclose(f);
	fflush(stdout);
}
示例#3
0
enum ofp_return_code ofp_arp_processing(odp_packet_t *pkt)
{
	struct ofp_arphdr *arp;
	struct ofp_ifnet *dev = odp_packet_user_ptr(*pkt);
	struct ofp_ifnet *outdev = dev;
	uint16_t vlan = dev->vlan;
	uint8_t inner_from_mac[OFP_ETHER_ADDR_LEN];
	uint32_t is_ours;

	arp = (struct ofp_arphdr *)odp_packet_l3_ptr(*pkt, NULL);

	if (odp_unlikely(arp == NULL)) {
		OFP_DBG("arp is NULL");
		return OFP_PKT_DROP;
	}

	/* save the received arp info */
	if (odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REPLY)
		ofp_add_mac(dev, arp->ip_src, arp->eth_src);

	OFP_DBG("Device IP: %s, Packet Dest IP: %s",
		ofp_print_ip_addr(dev->ip_addr),
		ofp_print_ip_addr(arp->ip_dst));

	/* Check for VXLAN interface */
	if (odp_unlikely(ofp_if_type(dev) == OFP_IFT_VXLAN)) {
		ofp_vxlan_update_devices(*pkt, arp, &vlan, &dev, &outdev,
					 inner_from_mac);
	}

	is_ours = dev->ip_addr && dev->ip_addr == (ofp_in_addr_t)(arp->ip_dst);
	if (!is_ours && !global_param->arp.check_interface) {
		/* This may be for some other local interface. */
		uint32_t flags;
		struct ofp_nh_entry *nh;
		nh = ofp_get_next_hop(dev->vrf, arp->ip_dst, &flags);
		if (nh)
			is_ours = nh->flags & OFP_RTF_LOCAL;
	}
	/* on our interface an ARP request */
	if (is_ours &&
	    odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REQUEST) {
		struct ofp_arphdr tmp;
		struct ofp_ether_header tmp_eth;
		struct ofp_ether_vlan_header tmp_eth_vlan;
		void *l2_addr = odp_packet_l2_ptr(*pkt, NULL);
		struct ofp_ether_header *eth =
			(struct ofp_ether_header *)l2_addr;
		struct ofp_ether_vlan_header *eth_vlan =
			(struct ofp_ether_vlan_header *)l2_addr;

		ofp_add_mac(dev, arp->ip_src, arp->eth_src);
		if (vlan)
			tmp_eth_vlan = *eth_vlan;
		else
			tmp_eth = *eth;

		OFP_DBG("Reply to ARPOP_REQ from ip %s"
#ifdef SP
			"on IF %d"
#endif
			" mac %s ip %s",
			ofp_print_ip_addr(arp->ip_src),
#ifdef SP
			dev->linux_index,
#endif
			ofp_print_mac(dev->mac),
			ofp_print_ip_addr(arp->ip_dst));
		tmp = *arp;
		tmp.ip_dst = arp->ip_src;
		tmp.ip_src = arp->ip_dst;
		memcpy(&tmp.eth_dst, &arp->eth_src, OFP_ETHER_ADDR_LEN);
		memcpy(&tmp.eth_src, dev->mac, OFP_ETHER_ADDR_LEN);
		tmp.op = odp_cpu_to_be_16(OFP_ARPOP_REPLY);
		*arp = tmp;

		if (vlan) {
			memcpy(tmp_eth_vlan.evl_dhost, &arp->eth_dst,
				OFP_ETHER_ADDR_LEN);
			memcpy(tmp_eth_vlan.evl_shost, &arp->eth_src,
				OFP_ETHER_ADDR_LEN);
			*eth_vlan = tmp_eth_vlan;
		} else {
			memcpy(tmp_eth.ether_dhost, &arp->eth_dst,
				OFP_ETHER_ADDR_LEN);
			memcpy(tmp_eth.ether_shost, &arp->eth_src,
				OFP_ETHER_ADDR_LEN);
			*eth = tmp_eth;
		}

		if (odp_unlikely(ofp_if_type(dev) == OFP_IFT_VXLAN)) {
			/* Restore the original vxlan header and
			   update the addresses */
			ofp_vxlan_restore_and_update_header
				(*pkt, outdev, inner_from_mac);
		}

		return send_pkt_out(outdev, *pkt);
	}
	return OFP_PKT_CONTINUE;
}
示例#4
0
enum ofp_return_code ofp_arp_processing(odp_packet_t pkt)
{
	struct ofp_arphdr *arp;
	struct ofp_ifnet *dev = odp_packet_user_ptr(pkt);
	struct ofp_ifnet *outdev = dev;
	uint16_t vlan = dev->vlan;
	uint8_t inner_from_mac[OFP_ETHER_ADDR_LEN];

	arp = (struct ofp_arphdr *)odp_packet_l3_ptr(pkt, NULL);

	if (odp_unlikely(arp == NULL)) {
		OFP_DBG("arp is NULL");
		return OFP_PKT_DROP;
	}

	/* save the received arp info */
	if (odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REPLY)
		ofp_add_mac(dev, arp->ip_src, arp->eth_src);

	OFP_DBG("Device IP: %s, Packet Dest IP: %s",
		ofp_print_ip_addr(dev->ip_addr),
		ofp_print_ip_addr(arp->ip_dst));

	/* Check for VXLAN interface */
	if (odp_unlikely(!PHYS_PORT(dev->port))) {
		switch (dev->port) {
		case GRE_PORTS:
			/* Never happens. */
			break;
		case VXLAN_PORTS: {
			ofp_vxlan_update_devices(arp, &vlan, &dev, &outdev,
						 inner_from_mac);
			break;
		}
		} /* switch */
	}

	/* on our interface an ARP request */
	if ((dev->ip_addr) && dev->ip_addr == (ofp_in_addr_t)(arp->ip_dst) &&
	    odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REQUEST) {
		struct ofp_arphdr tmp;
		struct ofp_ether_header tmp_eth;
		struct ofp_ether_vlan_header tmp_eth_vlan;
		void *l2_addr = odp_packet_l2_ptr(pkt, NULL);
		struct ofp_ether_header *eth =
			(struct ofp_ether_header *)l2_addr;
		struct ofp_ether_vlan_header *eth_vlan =
			(struct ofp_ether_vlan_header *)l2_addr;

		ofp_add_mac(dev, arp->ip_src, arp->eth_src);
		if (vlan)
			tmp_eth_vlan = *eth_vlan;
		else
			tmp_eth = *eth;

		OFP_DBG("Reply to ARPOP_REQ from ip %s"
#ifdef SP
			"on IF %d"
#endif
			" mac %s ip %s",
			ofp_print_ip_addr(arp->ip_src),
#ifdef SP
			dev->linux_index,
#endif
			ofp_print_mac(dev->mac),
			ofp_print_ip_addr(arp->ip_dst));
		tmp = *arp;
		tmp.ip_dst = arp->ip_src;
		tmp.ip_src = arp->ip_dst;
		memcpy(&tmp.eth_dst, &arp->eth_src, OFP_ETHER_ADDR_LEN);
		memcpy(&tmp.eth_src, dev->mac, OFP_ETHER_ADDR_LEN);
		tmp.op = odp_cpu_to_be_16(OFP_ARPOP_REPLY);
		*arp = tmp;

		if (vlan) {
			memcpy(tmp_eth_vlan.evl_dhost, &arp->eth_dst,
				OFP_ETHER_ADDR_LEN);
			memcpy(tmp_eth_vlan.evl_shost, &arp->eth_src,
				OFP_ETHER_ADDR_LEN);
			*eth_vlan = tmp_eth_vlan;
		} else {
			memcpy(tmp_eth.ether_dhost, &arp->eth_dst,
				OFP_ETHER_ADDR_LEN);
			memcpy(tmp_eth.ether_shost, &arp->eth_src,
				OFP_ETHER_ADDR_LEN);
			*eth = tmp_eth;
		}

		if (odp_unlikely(!PHYS_PORT(dev->port))) {
			switch (dev->port) {
			case GRE_PORTS:
				/* Never happens. */
				break;
			case VXLAN_PORTS: {
				/* Restore the original vxlan header and
				   update the addresses */
				ofp_vxlan_restore_and_update_header
					(pkt, outdev, inner_from_mac);
				break;
			}
			} /* switch */
		} /* not phys port */

		return send_pkt_out(outdev, pkt);
	}
	return OFP_PKT_CONTINUE;
}