Exemplo n.º 1
0
int     btree_remove(node_bt *list, node_bt *node, int(*func)(void*,void*), void *key)
{
  node_bt *parent;
  node_bt **buff;
  
  if (list == node)
  {
    if (remove_root(list) == 0)
      return 0;
    else
      return -1;  
  }
  parent = btree_search(list, key, func);
  if (parent->left == node) 
  {
    buff = &parent->left; 
  }
  else 
  {
    buff = &parent->right;
  }
  
  remove_not_root(node, buff);
  
  return 0;
}
Exemplo n.º 2
0
static int install_tbf(struct rtnl_handle *rth, int ifindex, int rate, int burst)
{
	struct qdisc_opt opt = {
		.kind = "tbf",
		.handle = 0x00010000,
		.parent = TC_H_ROOT,
		.rate = rate,
		.buffer = burst,
		.latency = conf_latency,
		.qdisc = qdisc_tbf,
	};

	return tc_qdisc_modify(rth, ifindex, RTM_NEWQDISC, NLM_F_EXCL|NLM_F_CREATE, &opt);
}

static int install_htb(struct rtnl_handle *rth, int ifindex, int rate, int burst)
{
	struct qdisc_opt opt1 = {
		.kind = "htb",
		.handle = 0x00010000,
		.parent = TC_H_ROOT,
		.quantum = conf_r2q,
		.defcls = 1,
		.qdisc = qdisc_htb_root,
	};

	struct qdisc_opt opt2 = {
		.kind = "htb",
		.handle = 0x00010001,
		.parent = 0x00010000,
		.rate = rate,
		.buffer = burst,
		.quantum = conf_quantum,
		.qdisc = qdisc_htb_class,
	};


	if (tc_qdisc_modify(rth, ifindex, RTM_NEWQDISC, NLM_F_EXCL|NLM_F_CREATE, &opt1))
		return -1;

	if (tc_qdisc_modify(rth, ifindex, RTM_NEWTCLASS, NLM_F_EXCL|NLM_F_CREATE, &opt2))
		return -1;

	return 0;
}

static int install_police(struct rtnl_handle *rth, int ifindex, int rate, int burst)
{
	__u32 rtab[256];
	struct rtattr *tail, *tail1, *tail2, *tail3;
	int Rcell_log = -1;
	int mtu = conf_mtu, flowid = 1;
	unsigned int linklayer  = LINKLAYER_ETHERNET; /* Assume ethernet */

	struct {
			struct nlmsghdr 	n;
			struct tcmsg 		t;
			char buf[TCA_BUF_MAX];
	} req;

	struct qdisc_opt opt1 = {
		.kind = "ingress",
		.handle = 0xffff0000,
		.parent = TC_H_INGRESS,
	};

	struct sel {
		struct tc_u32_sel sel;
		struct tc_u32_key key;
	} sel = {
		.sel.nkeys = 1,
		.sel.flags = TC_U32_TERMINAL,
//		.key.off = 12,
	};

	struct tc_police police = {
		.action = TC_POLICE_SHOT,
		.rate.rate = rate,
		.rate.mpu = conf_mpu,
		.limit = (double)rate * conf_latency + burst,
		.burst = tc_calc_xmittime(rate, burst),
	};

	if (tc_qdisc_modify(rth, ifindex, RTM_NEWQDISC, NLM_F_EXCL|NLM_F_CREATE, &opt1))
		return -1;

	if (tc_calc_rtable(&police.rate, rtab, Rcell_log, mtu, linklayer) < 0) {
		log_ppp_error("shaper: failed to calculate ceil rate table.\n");
		return -1;
	}

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_EXCL|NLM_F_CREATE;
	req.n.nlmsg_type = RTM_NEWTFILTER;
	req.t.tcm_family = AF_UNSPEC;
	req.t.tcm_ifindex = ifindex;
	req.t.tcm_handle = 1;
	req.t.tcm_parent = 0xffff0000;

	req.t.tcm_info = TC_H_MAKE(100 << 16, ntohs(ETH_P_ALL));

	addattr_l(&req.n, sizeof(req), TCA_KIND, "u32", 4);

	tail = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_OPTIONS, NULL, 0);

	tail1 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_U32_ACT, NULL, 0);

	tail2 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, 1, NULL, 0);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, "police", 7);

	tail3 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_OPTIONS, NULL, 0);
	addattr_l(&req.n, MAX_MSG, TCA_POLICE_TBF, &police, sizeof(police));
	addattr_l(&req.n, MAX_MSG, TCA_POLICE_RATE, rtab, 1024);
	tail3->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail3;

	tail2->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail2;

	tail1->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail1;

	addattr_l(&req.n, MAX_MSG, TCA_U32_CLASSID, &flowid, 4);
	addattr_l(&req.n, MAX_MSG, TCA_U32_SEL, &sel, sizeof(sel));
	tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail;

	if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
		return -1;

	return 0;
}

static int install_htb_ifb(struct rtnl_handle *rth, int ifindex, __u32 priority, int rate, int burst)
{
	struct rtattr *tail, *tail1, *tail2, *tail3;

	struct {
			struct nlmsghdr 	n;
			struct tcmsg 		t;
			char buf[TCA_BUF_MAX];
	} req;

	struct qdisc_opt opt1 = {
		.kind = "htb",
		.handle = 0x00010000 + priority,
		.parent = 0x00010000,
		.rate = rate,
		.buffer = burst,
		.quantum = conf_quantum,
		.qdisc = qdisc_htb_class,
	};

	struct qdisc_opt opt2 = {
		.kind = "ingress",
		.handle = 0xffff0000,
		.parent = TC_H_INGRESS,
	};

	struct sel {
		struct tc_u32_sel sel;
		struct tc_u32_key key;
	} sel = {
		.sel.nkeys = 1,
		.sel.flags = TC_U32_TERMINAL,
		.key.off = 0,
	};

	struct tc_skbedit p1 = {
		.action = TC_ACT_PIPE,
	};

	struct tc_mirred p2 = {
		.eaction = TCA_EGRESS_REDIR,
		.action = TC_ACT_STOLEN,
		.ifindex = conf_ifb_ifindex,
	};

	if (tc_qdisc_modify(rth, conf_ifb_ifindex, RTM_NEWTCLASS, NLM_F_EXCL|NLM_F_CREATE, &opt1))
		return -1;

	if (tc_qdisc_modify(rth, ifindex, RTM_NEWQDISC, NLM_F_EXCL|NLM_F_CREATE, &opt2))
		return -1;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_EXCL|NLM_F_CREATE;
	req.n.nlmsg_type = RTM_NEWTFILTER;
	req.t.tcm_family = AF_UNSPEC;
	req.t.tcm_ifindex = ifindex;
	req.t.tcm_handle = 1;
	req.t.tcm_parent = 0xffff0000;

	req.t.tcm_info = TC_H_MAKE(100 << 16, ntohs(ETH_P_ALL));


	addattr_l(&req.n, sizeof(req), TCA_KIND, "u32", 4);

	tail = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_OPTIONS, NULL, 0);

	tail1 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_U32_ACT, NULL, 0);

	// action skbedit priority X pipe
	tail2 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, 1, NULL, 0);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, "skbedit", 8);

	tail3 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_OPTIONS, NULL, 0);
	addattr_l(&req.n, MAX_MSG, TCA_SKBEDIT_PARMS, &p1, sizeof(p1));
	priority--;
	addattr_l(&req.n, MAX_MSG, TCA_SKBEDIT_PRIORITY, &priority, sizeof(priority));
	tail3->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail3;

	tail2->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail2;

	tail1->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail1;

	// action mirred egress redirect dev ifb0
	tail2 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, 2, NULL, 0);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, "mirred", 7);

	tail3 = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, MAX_MSG, TCA_ACT_OPTIONS, NULL, 0);
	addattr_l(&req.n, MAX_MSG, TCA_MIRRED_PARMS, &p2, sizeof(p2));
	tail3->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail3;

	tail2->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail2;

	tail1->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail1;
  //

	addattr32(&req.n, TCA_BUF_MAX, TCA_U32_CLASSID, 1);
	addattr_l(&req.n, MAX_MSG, TCA_U32_SEL, &sel, sizeof(sel));
	tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail;

	if (rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0) < 0)
		return -1;

	return 0;
}

static int install_fwmark(struct rtnl_handle *rth, int ifindex, int parent)
{
	struct rtattr *tail;

	struct {
			struct nlmsghdr 	n;
			struct tcmsg 		t;
			char buf[1024];
	} req;

	memset(&req, 0, sizeof(req) - 1024);

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_EXCL|NLM_F_CREATE;
	req.n.nlmsg_type = RTM_NEWTFILTER;
	req.t.tcm_family = AF_UNSPEC;
	req.t.tcm_ifindex = ifindex;
	req.t.tcm_handle = conf_fwmark;
	req.t.tcm_parent = parent;
	req.t.tcm_info = TC_H_MAKE(90 << 16, ntohs(ETH_P_IP));

	addattr_l(&req.n, sizeof(req), TCA_KIND, "fw", 3);
	tail = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, TCA_BUF_MAX, TCA_OPTIONS, NULL, 0);
	addattr32(&req.n, TCA_BUF_MAX, TCA_FW_CLASSID, TC_H_MAKE(1 << 16, 0));
	tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail;
	return rtnl_talk(rth, &req.n, 0, 0, NULL, NULL, NULL, 0);
}

static int remove_root(struct rtnl_handle *rth, int ifindex)
{
	struct qdisc_opt opt = {
		.handle = 0x00010000,
		.parent = TC_H_ROOT,
	};

	return tc_qdisc_modify(rth, ifindex, RTM_DELQDISC, 0, &opt);
}

static int remove_ingress(struct rtnl_handle *rth, int ifindex)
{
	struct qdisc_opt opt = {
		.handle = 0xffff0000,
		.parent = TC_H_INGRESS,
	};

	return tc_qdisc_modify(rth, ifindex, RTM_DELQDISC, 0, &opt);
}

static int remove_htb_ifb(struct rtnl_handle *rth, int ifindex, int priority)
{
	struct qdisc_opt opt = {
		.handle = 0x00010000 + priority,
		.parent = 0x00010000,
	};

	return tc_qdisc_modify(rth, conf_ifb_ifindex, RTM_DELTCLASS, 0, &opt);
}

int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed, int up_burst, int idx)
{
	struct rtnl_handle *rth = net->rtnl_get();
	int r = 0;

	if (!rth) {
		log_ppp_error("shaper: cannot open rtnetlink\n");
		return -1;
	}

	if (down_speed) {
		down_speed = down_speed * 1000 / 8;
		down_burst = down_burst ? down_burst : conf_down_burst_factor * down_speed;

		if (conf_down_limiter == LIM_TBF)
			r = install_tbf(rth, ses->ifindex, down_speed, down_burst);
		else {
			r = install_htb(rth, ses->ifindex, down_speed, down_burst);
			if (r == 0)
				r = install_leaf_qdisc(rth, ses->ifindex, 0x00010001, 0x00020000);
		}
	}

	if (up_speed) {
		up_speed = up_speed * 1000 / 8;
		up_burst = up_burst ? up_burst : conf_up_burst_factor * up_speed;

		if (conf_up_limiter == LIM_POLICE)
			r = install_police(rth, ses->ifindex, up_speed, up_burst);
		else {
			r = install_htb_ifb(rth, ses->ifindex, idx, up_speed, up_burst);
			if (r == 0)
				r = install_leaf_qdisc(rth, conf_ifb_ifindex, 0x00010000 + idx, idx << 16);
		}
	}

	if (conf_fwmark)
		install_fwmark(rth, ses->ifindex, 0x00010000);

	net->rtnl_put(rth);

	return r;
}

int remove_limiter(struct ap_session *ses, int idx)
{
	struct rtnl_handle *rth = net->rtnl_get();

	if (!rth) {
		log_ppp_error("shaper: cannot open rtnetlink\n");
		return -1;
	}

	remove_root(rth, ses->ifindex);
	remove_ingress(rth, ses->ifindex);

	if (conf_up_limiter == LIM_HTB)
		remove_htb_ifb(rth, ses->ifindex, idx);

	net->rtnl_put(rth);

	return 0;
}

int init_ifb(const char *name)
{
	struct rtnl_handle rth;
	struct rtattr *tail;
	struct ifreq ifr;
	int r;
	int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);

	struct {
			struct nlmsghdr 	n;
			struct tcmsg 		t;
			char buf[TCA_BUF_MAX];
	} req;

	struct qdisc_opt opt = {
		.kind = "htb",
		.handle = 0x00010000,
		.parent = TC_H_ROOT,
		.quantum = conf_r2q,
		.qdisc = qdisc_htb_root,
	};

	if (system("modprobe -q ifb"))
		log_warn("failed to load ifb kernel module\n");

	memset(&ifr, 0, sizeof(ifr));
	strcpy(ifr.ifr_name, name);

	if (ioctl(sock_fd, SIOCGIFINDEX, &ifr)) {
		log_emerg("shaper: ioctl(SIOCGIFINDEX): %s\n", strerror(errno));
		close(sock_fd);
		return -1;
	}

	conf_ifb_ifindex = ifr.ifr_ifindex;

	ifr.ifr_flags |= IFF_UP;

	if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr)) {
		log_emerg("shaper: ioctl(SIOCSIFINDEX): %s\n", strerror(errno));
		close(sock_fd);
		return -1;
	}

	if (rtnl_open(&rth, 0)) {
		log_emerg("shaper: cannot open rtnetlink\n");
		close(sock_fd);
		return -1;
	}

	tc_qdisc_modify(&rth, conf_ifb_ifindex, RTM_DELQDISC, 0, &opt);

	r = tc_qdisc_modify(&rth, conf_ifb_ifindex, RTM_NEWQDISC, NLM_F_CREATE | NLM_F_REPLACE, &opt);
	if (r)
		goto out;

	memset(&req, 0, sizeof(req));

	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_EXCL|NLM_F_CREATE;
	req.n.nlmsg_type = RTM_NEWTFILTER;
	req.t.tcm_family = AF_UNSPEC;
	req.t.tcm_ifindex = conf_ifb_ifindex;
	req.t.tcm_handle = 1;
	req.t.tcm_parent = 0x00010000;
	req.t.tcm_info = TC_H_MAKE(100 << 16, ntohs(ETH_P_ALL));

	addattr_l(&req.n, sizeof(req), TCA_KIND, "flow", 5);

	tail = NLMSG_TAIL(&req.n);
	addattr_l(&req.n, TCA_BUF_MAX, TCA_OPTIONS, NULL, 0);
	addattr32(&req.n, TCA_BUF_MAX, TCA_FLOW_KEYS, 1 << FLOW_KEY_PRIORITY);
	addattr32(&req.n, TCA_BUF_MAX, TCA_FLOW_MODE, FLOW_MODE_MAP);
	tail->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)tail;

	r = rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL, 0);

out:
	rtnl_close(&rth);
	close(sock_fd);

	return r;
}
Exemplo n.º 3
0
segtable* add_segment
   (segtable*	st,
	unspos		pos1,
	unspos		pos2,
	unspos		length,
	score		s,
	int			id)
	{
	u32			newSize;
	size_t		bytesNeeded;
	segment*	seg, *parent;
	segment		tempSeg;
	int			ix, pIx;
	int			tied, stopped;

//	fprintf (stderr, "add " unsposSlashSFmt " " unsposFmt " " scoreFmtSimple "; id %d\n",
//	               pos1+1, "+",
//	               pos2+1, ((id & rcf_rev) != 0)? "-" : "+",
//	               length, s, id);

	//////////
	// add the segment to the table, enlarging the table if needed, but
	// discarding the segment if it is low-scoring and the table has met its
	// coverage limit
	//////////

	// if the table is already full and this segment scores less than the
	// lowest score in the table, discard it

	if ((st->len > 0)
	 && (st->coverageLimit != 0)
	 && (st->coverage >= st->coverageLimit)
	 && (s < st->lowScore))
		return st;

	// if there's no room for the new segment, re-allocate

	if (st->len >= st->size)
		{
		newSize     = st->size + 100 + (st->size / 3);
		bytesNeeded = segtable_bytes (newSize);
		if (bytesNeeded > mallocLimit) goto overflow;
		st = (segtable*) realloc_or_die ("add_segment", st, bytesNeeded);
		st->size = newSize;
		}

	// add the segment, by appending it at the end

	seg = &st->seg[st->len++];
	seg->pos1     = pos1;
	seg->pos2     = pos2;
	seg->length   = length;
	seg->s        = s;
	seg->id       = id;
	seg->filter   = false;
	seg->scoreCov = (possum) length;

	st->coverage += length;
	if ((st->len == 1) || (s < st->lowScore)) st->lowScore = s;

	//////////
	// handle the transition between the two table states
	//	below-the-coverage-limit:  table is kept as a simple list
	//	met-the-coverage-limit:    table is kept as a proper min-heap
	//////////

	// if this segment leaves us below the limit, we're done

	if ((st->coverageLimit == 0)
	 || (st->coverage < st->coverageLimit))
		return st;

	// if this is the first time we've reached the limit, sort the segments to
	// create a proper min-heap, and add the tied-score information
	// nota bene:  if we reach here, st->coverageLimit > 0 and
	//             st->coverage >= st->coverageLimit

	if (st->coverage - length < st->coverageLimit)
		{
		sort_segments (st, qSegmentsByIncreasingScore);
		record_tie_scores (st);
		#ifdef debugBinaryHeap
		fprintf       (stderr, "\nafter sort:\n");
		dump_segments (stderr, st, NULL, NULL);
		validate_heap (st, "after sort");
		#endif // debugBinaryHeap
		goto prune;
		}

	//////////
	// maintain the min-heap property
	//////////

	#ifdef debugBinaryHeap
	//fprintf       (stderr, "\nbefore percolation:\n");
	//dump_segments (stderr, st, NULL, NULL);
	#endif // debugBinaryHeap

	// the rest of the list is a proper min-heap, so percolate the new segment
	// up the tree, while maintaining the tied-score information
	// nota bene:  if we reach here, length >= 2

	tied = false;
	for (ix=st->len-1 ; ix>0 ; )
		{
		pIx    = (ix-1) / 2;
		seg    = &st->seg[ix];
		parent = &st->seg[pIx];

		if (seg->s >= parent->s)
			{ tied = (seg->s == parent->s);  break; }

		// swap this segment with its parent, and adjust old parent's tied-score
		// subheap

		tempSeg = *seg;  *seg = *parent;  *parent = tempSeg;
		record_tie_score (st, ix);

		ix = pIx;
		}

	record_tie_score (st, ix);

	// if the new segment tied an existing score, we must continue to percolate
	// the tied-score info up the tree

	if (tied)
		{
		stopped = false;
		for (ix=(ix-1)/2 ; ix>0 ; ix=(ix-1)/2)
			{
			if (!record_tie_score (st, ix))
				{ stopped = true;  break; }
			}
		if (!stopped) record_tie_score (st, 0);
		}

	#ifdef debugBinaryHeap
	fprintf       (stderr, "\nafter percolation:\n");
	dump_segments (stderr, st, NULL, NULL);
	validate_heap (st, "after percolation");
	#endif // debugBinaryHeap

	//////////
	// remove low-scoring segments
	//////////

prune:

	// if removing the minimum scoring subheap would bring us below the
	// limit, no pruning is necessary

	if (st->coverage - st->seg[0].scoreCov < st->coverageLimit)
		return st;

	// otherwise, we must remove subheaps as long as doing so leaves us at or
	// above the limit

	while (st->coverage - st->seg[0].scoreCov >= st->coverageLimit)
		{
		s = st->seg[0].s;
		while (st->seg[0].s == s)
			{
			remove_root (st);
			#ifdef debugBinaryHeap
			fprintf       (stderr, "\nafter a pruning:\n");
			dump_segments (stderr, st, NULL, NULL);
			validate_heap (st, "after pruning");
			#endif // debugBinaryHeap
			}
		}

	st->lowScore = st->seg[0].s;

	#ifdef debugBinaryHeap
	fprintf       (stderr, "\nafter pruning:\n");
	dump_segments (stderr, st, NULL, NULL);
	validate_heap (st, "after pruning");
	#endif // debugBinaryHeap

	return st;

// failure exits

#define suggestions " consider using lastz_m40,"                              \
                    " or setting max_malloc_index for a special build,"       \
                    " or raising scoring threshold (--hspthresh or --exact)," \
                    " or break your target sequence into smaller pieces"

overflow:
	suicidef ("in add_segment()\n"
	          "table size (%s for %s segments) exceeds allocation limit of %s;\n"
	          suggestions,
	          commatize(bytesNeeded),
	          commatize(newSize),
	          commatize(mallocLimit));
	return NULL; // (doesn't get here)
	}
Exemplo n.º 4
0
T BST<T>::remove(T item) {
	
		// 	remember to take care of the root case

	BinaryNode<T> *our_parent = NULL;
	BinaryNode<T> *our_guy = root;
	BinaryNode<T> *tmp;
	T our_data;

	while (our_guy != NULL) {  // Traverse the tree down some path
		if (item == our_guy->get_data())
			break;
		else if (item < our_guy->get_data()){  // Go left
			our_parent = our_guy;
			our_guy = our_guy->get_lhs();
		}
		else{  // Go right
			our_parent = our_guy;
			our_guy = our_guy->get_rhs();
		}
	}

	if (our_guy == NULL){
		throw 1; // item not found
		return our_data; //VS
	}
	//now we know our item is inside our BST


	// NOW WE CAN GET TO OUR 3 CASES OF DELETING. WOOOO
	our_data = our_guy->get_data();

	if (our_guy == root){
		our_data = remove_root();
		return our_data;
	}

	if (our_guy->get_rhs() == NULL && our_guy->get_lhs() == NULL){ //no children lol
		if (our_parent->get_rhs() == our_guy){ //we want to NULL the rhs
			delete our_parent->get_rhs();
			our_parent->set_rhs(NULL);
			return our_data;
		}

		else{ //else, NULL lhs
			delete our_parent->get_lhs();
			our_parent->set_lhs(NULL);
			return our_data;
		}
	}

	else if (our_guy->get_rhs() == NULL && our_guy->get_lhs() != NULL){ // one child -> our lhs is a kid

		tmp = our_guy->get_lhs(); //saved the child in tmp
		
		if (our_parent->get_rhs() == our_guy){
			delete our_parent->get_rhs();
			our_parent->set_rhs(tmp);
			return our_data;

		}

		else{ //else, NULL lhs
			delete our_parent->get_lhs();
			our_parent->set_lhs(tmp);
			return our_data;
		}

	}

	else if (our_guy->get_lhs() == NULL && our_guy->get_rhs() != NULL){

		tmp = our_guy->get_rhs(); //saved the child in tmp 

		if (our_parent->get_rhs() == our_guy){
			delete our_parent->get_rhs();
			our_parent->set_rhs(tmp);
			return our_data;

		}

		else{ //else, NULL lhs
			delete our_parent->get_lhs();
			our_parent->set_lhs(tmp);
			return our_data;
		}


	}


	else{ //two child case
		// 	saving max data into an int or someshit, then removing max's shit, then overwriting the data

		BinaryNode<T> *max;
		max = find_max(our_guy->get_lhs());
		T max_data = max->get_data();

		remove(max->get_data());




		our_guy->set_data(max_data);


		return our_data;
	}






	// TODO: Implement this function
	throw 1;
}