return (uint8_t)(sum / count);
 }
 
+/**
+ * batadv_iv_ogm_orig_free - free the private resources allocated for this
+ *  orig_node
+ * @orig_node: the orig_node for which the resources have to be free'd
+ */
+static void batadv_iv_ogm_orig_free(struct batadv_orig_node *orig_node)
+{
+       kfree(orig_node->bat_iv.bcast_own);
+       kfree(orig_node->bat_iv.bcast_own_sum);
+}
+
+/**
+ * batadv_iv_ogm_orig_add_if - change the private structures of the orig_node to
+ *  include the new hard-interface
+ * @orig_node: the orig_node that has to be changed
+ * @max_if_num: the current amount of interfaces
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node,
+                                    int max_if_num)
+{
+       void *data_ptr;
+       size_t data_size, old_size;
+       int ret = -ENOMEM;
+
+       spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
+
+       data_size = max_if_num * sizeof(unsigned long) * BATADV_NUM_WORDS;
+       old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS;
+       data_ptr = kmalloc(data_size, GFP_ATOMIC);
+       if (!data_ptr)
+               goto unlock;
+
+       memcpy(data_ptr, orig_node->bat_iv.bcast_own, old_size);
+       kfree(orig_node->bat_iv.bcast_own);
+       orig_node->bat_iv.bcast_own = data_ptr;
+
+       data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
+       if (!data_ptr) {
+               kfree(orig_node->bat_iv.bcast_own);
+               goto unlock;
+       }
+
+       memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
+              (max_if_num - 1) * sizeof(uint8_t));
+       kfree(orig_node->bat_iv.bcast_own_sum);
+       orig_node->bat_iv.bcast_own_sum = data_ptr;
+
+       ret = 0;
+
+unlock:
+       spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
+
+       return ret;
+}
+
+/**
+ * batadv_iv_ogm_orig_del_if - change the private structures of the orig_node to
+ *  exclude the removed interface
+ * @orig_node: the orig_node that has to be changed
+ * @max_if_num: the current amount of interfaces
+ * @del_if_num: the index of the interface being removed
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node,
+                                    int max_if_num, int del_if_num)
+{
+       int chunk_size,  ret = -ENOMEM, if_offset;
+       void *data_ptr = NULL;
+
+       spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
+
+       /* last interface was removed */
+       if (max_if_num == 0)
+               goto free_bcast_own;
+
+       chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS;
+       data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
+       if (!data_ptr)
+               goto unlock;
+
+       /* copy first part */
+       memcpy(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size);
+
+       /* copy second part */
+       memcpy((char *)data_ptr + del_if_num * chunk_size,
+              orig_node->bat_iv.bcast_own + ((del_if_num + 1) * chunk_size),
+              (max_if_num - del_if_num) * chunk_size);
+
+free_bcast_own:
+       kfree(orig_node->bat_iv.bcast_own);
+       orig_node->bat_iv.bcast_own = data_ptr;
+
+       if (max_if_num == 0)
+               goto free_own_sum;
+
+       data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
+       if (!data_ptr) {
+               kfree(orig_node->bat_iv.bcast_own);
+               goto unlock;
+       }
+
+       memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
+              del_if_num * sizeof(uint8_t));
+
+       if_offset = (del_if_num + 1) * sizeof(uint8_t);
+       memcpy((char *)data_ptr + del_if_num * sizeof(uint8_t),
+              orig_node->bat_iv.bcast_own_sum + if_offset,
+              (max_if_num - del_if_num) * sizeof(uint8_t));
+
+free_own_sum:
+       kfree(orig_node->bat_iv.bcast_own_sum);
+       orig_node->bat_iv.bcast_own_sum = data_ptr;
+
+       ret = 0;
+unlock:
+       spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
+
+       return ret;
+}
+
 /**
  * batadv_iv_ogm_orig_get - retrieve or create (if does not exist) an originator
  * @bat_priv: the bat priv with all the soft interface information
        .bat_neigh_cmp = batadv_iv_ogm_neigh_cmp,
        .bat_neigh_is_equiv_or_better = batadv_iv_ogm_neigh_is_eob,
        .bat_orig_print = batadv_iv_ogm_orig_print,
+       .bat_orig_free = batadv_iv_ogm_orig_free,
+       .bat_orig_add_if = batadv_iv_ogm_orig_add_if,
+       .bat_orig_del_if = batadv_iv_ogm_orig_del_if,
 };
 
 int __init batadv_iv_init(void)
 
        batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, -1,
                                  "originator timed out");
 
+       if (orig_node->bat_priv->bat_algo_ops->bat_orig_free)
+               orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node);
+
        kfree(orig_node->tt_buff);
-       kfree(orig_node->bat_iv.bcast_own);
-       kfree(orig_node->bat_iv.bcast_own_sum);
        kfree(orig_node);
 }
 
        return 0;
 }
 
-static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node,
-                                  int max_if_num)
-{
-       void *data_ptr;
-       size_t data_size, old_size;
-
-       data_size = max_if_num * sizeof(unsigned long) * BATADV_NUM_WORDS;
-       old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS;
-       data_ptr = kmalloc(data_size, GFP_ATOMIC);
-       if (!data_ptr)
-               return -ENOMEM;
-
-       memcpy(data_ptr, orig_node->bat_iv.bcast_own, old_size);
-       kfree(orig_node->bat_iv.bcast_own);
-       orig_node->bat_iv.bcast_own = data_ptr;
-
-       data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
-       if (!data_ptr)
-               return -ENOMEM;
-
-       memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
-              (max_if_num - 1) * sizeof(uint8_t));
-       kfree(orig_node->bat_iv.bcast_own_sum);
-       orig_node->bat_iv.bcast_own_sum = data_ptr;
-
-       return 0;
-}
-
 int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
                            int max_if_num)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+       struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
        struct batadv_hashtable *hash = bat_priv->orig_hash;
        struct hlist_head *head;
        struct batadv_orig_node *orig_node;
 
                rcu_read_lock();
                hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
-                       spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
-                       ret = batadv_orig_node_add_if(orig_node, max_if_num);
-                       spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
-
+                       ret = 0;
+                       if (bao->bat_orig_add_if)
+                               ret = bao->bat_orig_add_if(orig_node,
+                                                          max_if_num);
                        if (ret == -ENOMEM)
                                goto err;
                }
        return -ENOMEM;
 }
 
-static int batadv_orig_node_del_if(struct batadv_orig_node *orig_node,
-                                  int max_if_num, int del_if_num)
-{
-       int chunk_size, if_offset;
-       void *data_ptr = NULL;
-
-       /* last interface was removed */
-       if (max_if_num == 0)
-               goto free_bcast_own;
-
-       chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS;
-       data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
-       if (!data_ptr)
-               return -ENOMEM;
-
-       /* copy first part */
-       memcpy(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size);
-
-       /* copy second part */
-       memcpy((char *)data_ptr + del_if_num * chunk_size,
-              orig_node->bat_iv.bcast_own + ((del_if_num + 1) * chunk_size),
-              (max_if_num - del_if_num) * chunk_size);
-
-free_bcast_own:
-       kfree(orig_node->bat_iv.bcast_own);
-       orig_node->bat_iv.bcast_own = data_ptr;
-
-       if (max_if_num == 0)
-               goto free_own_sum;
-
-       data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
-       if (!data_ptr)
-               return -ENOMEM;
-
-       memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
-              del_if_num * sizeof(uint8_t));
-
-       if_offset = (del_if_num + 1) * sizeof(uint8_t);
-       memcpy((char *)data_ptr + del_if_num * sizeof(uint8_t),
-              orig_node->bat_iv.bcast_own_sum + if_offset,
-              (max_if_num - del_if_num) * sizeof(uint8_t));
-
-free_own_sum:
-       kfree(orig_node->bat_iv.bcast_own_sum);
-       orig_node->bat_iv.bcast_own_sum = data_ptr;
-
-       return 0;
-}
-
 int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
                            int max_if_num)
 {
        struct hlist_head *head;
        struct batadv_hard_iface *hard_iface_tmp;
        struct batadv_orig_node *orig_node;
+       struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
        uint32_t i;
        int ret;
 
 
                rcu_read_lock();
                hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
-                       spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
-                       ret = batadv_orig_node_del_if(orig_node, max_if_num,
-                                                     hard_iface->if_num);
-                       spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
-
+                       ret = 0;
+                       if (bao->bat_orig_del_if)
+                               ret = bao->bat_orig_del_if(orig_node,
+                                                          max_if_num,
+                                                          hard_iface->if_num);
                        if (ret == -ENOMEM)
                                goto err;
                }
 
  * @bat_neigh_is_equiv_or_better: check if neigh1 is equally good or
  *  better than neigh2 from the metric prospective
  * @bat_orig_print: print the originator table (optional)
+ * @bat_orig_free: free the resources allocated by the routing algorithm for an
+ *  orig_node object
+ * @bat_orig_add_if: ask the routing algorithm to apply the needed changes to
+ *  the orig_node due to a new hard-interface being added into the mesh
+ * @bat_orig_del_if: ask the routing algorithm to apply the needed changes to
+ *  the orig_node due to an hard-interface being removed from the mesh
  */
 struct batadv_algo_ops {
        struct hlist_node list;
                                             struct batadv_neigh_node *neigh2);
        /* orig_node handling API */
        void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq);
+       void (*bat_orig_free)(struct batadv_orig_node *orig_node);
+       int (*bat_orig_add_if)(struct batadv_orig_node *orig_node,
+                              int max_if_num);
+       int (*bat_orig_del_if)(struct batadv_orig_node *orig_node,
+                              int max_if_num, int del_if_num);
 };
 
 /**