DEFINE_MUTEX(fanout_mutex);
 EXPORT_SYMBOL_GPL(fanout_mutex);
 static LIST_HEAD(fanout_list);
+static u16 fanout_next_id;
 
 static void __fanout_link(struct sock *sk, struct packet_sock *po)
 {
        };
 }
 
+static bool __fanout_id_is_free(struct sock *sk, u16 candidate_id)
+{
+       struct packet_fanout *f;
+
+       list_for_each_entry(f, &fanout_list, list) {
+               if (f->id == candidate_id &&
+                   read_pnet(&f->net) == sock_net(sk)) {
+                       return false;
+               }
+       }
+       return true;
+}
+
+static bool fanout_find_new_id(struct sock *sk, u16 *new_id)
+{
+       u16 id = fanout_next_id;
+
+       do {
+               if (__fanout_id_is_free(sk, id)) {
+                       *new_id = id;
+                       fanout_next_id = id + 1;
+                       return true;
+               }
+
+               id++;
+       } while (id != fanout_next_id);
+
+       return false;
+}
+
 static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
 {
        struct packet_rollover *rollover = NULL;
                po->rollover = rollover;
        }
 
+       if (type_flags & PACKET_FANOUT_FLAG_UNIQUEID) {
+               if (id != 0) {
+                       err = -EINVAL;
+                       goto out;
+               }
+               if (!fanout_find_new_id(sk, &id)) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+               /* ephemeral flag for the first socket in the group: drop it */
+               flags &= ~(PACKET_FANOUT_FLAG_UNIQUEID >> 8);
+       }
+
        match = NULL;
        list_for_each_entry(f, &fanout_list, list) {
                if (f->id == id &&