Lines Matching +full:freq +full:- +full:table +full:- +full:hz

1 // SPDX-License-Identifier: GPL-2.0-or-later
36 /* FL hash table */
49 /* FL hash table lock: it protects only of GC */
57 DEFINE_STATIC_KEY_DEFERRED_FALSE(ipv6_flowlabel_exclusive, HZ);
63 fl = rcu_dereference(fl->next))
65 for (fl = rcu_dereference(fl->next); \
67 fl = rcu_dereference(fl->next))
70 for (sfl = rcu_dereference(np->ipv6_fl_list); \
72 sfl = rcu_dereference(sfl->next))
79 if (fl->label == label && net_eq(fl->fl_net, net)) in __fl_lookup()
91 if (fl && !atomic_inc_not_zero(&fl->users)) in fl_lookup()
99 return fl->share == IPV6_FL_S_EXCL || in fl_shared_exclusive()
100 fl->share == IPV6_FL_S_PROCESS || in fl_shared_exclusive()
101 fl->share == IPV6_FL_S_USER; in fl_shared_exclusive()
108 if (fl->share == IPV6_FL_S_PROCESS) in fl_free_rcu()
109 put_pid(fl->owner.pid); in fl_free_rcu()
110 kfree(fl->opt); in fl_free_rcu()
120 if (fl_shared_exclusive(fl) || fl->opt) in fl_free()
123 call_rcu(&fl->rcu, fl_free_rcu); in fl_free()
130 fl->lastuse = jiffies; in fl_release()
131 if (atomic_dec_and_test(&fl->users)) { in fl_release()
132 unsigned long ttd = fl->lastuse + fl->linger; in fl_release()
133 if (time_after(ttd, fl->expires)) in fl_release()
134 fl->expires = ttd; in fl_release()
135 ttd = fl->expires; in fl_release()
136 if (fl->opt && fl->share == IPV6_FL_S_EXCL) { in fl_release()
137 struct ipv6_txoptions *opt = fl->opt; in fl_release()
138 fl->opt = NULL; in fl_release()
163 if (atomic_read(&fl->users) == 0) { in ip6_fl_gc()
164 unsigned long ttd = fl->lastuse + fl->linger; in ip6_fl_gc()
165 if (time_after(ttd, fl->expires)) in ip6_fl_gc()
166 fl->expires = ttd; in ip6_fl_gc()
167 ttd = fl->expires; in ip6_fl_gc()
169 *flp = fl->next; in ip6_fl_gc()
177 flp = &fl->next; in ip6_fl_gc()
200 if (net_eq(fl->fl_net, net) && in ip6_fl_purge()
201 atomic_read(&fl->users) == 0) { in ip6_fl_purge()
202 *flp = fl->next; in ip6_fl_purge()
207 flp = &fl->next; in ip6_fl_purge()
218 fl->label = label & IPV6_FLOWLABEL_MASK; in fl_intern()
224 fl->label = htonl(get_random_u32())&IPV6_FLOWLABEL_MASK; in fl_intern()
225 if (fl->label) { in fl_intern()
226 lfl = __fl_lookup(net, fl->label); in fl_intern()
237 * done in ipv6_flowlabel_opt - sock is locked, so new entry in fl_intern()
240 lfl = __fl_lookup(net, fl->label); in fl_intern()
242 atomic_inc(&lfl->users); in fl_intern()
249 fl->lastuse = jiffies; in fl_intern()
250 fl->next = fl_ht[FL_HASH(fl->label)]; in fl_intern()
251 rcu_assign_pointer(fl_ht[FL_HASH(fl->label)], fl); in fl_intern()
271 struct ip6_flowlabel *fl = sfl->fl; in __fl6_sock_lookup()
273 if (fl->label == label && atomic_inc_not_zero(&fl->users)) { in __fl6_sock_lookup()
274 fl->lastuse = jiffies; in __fl6_sock_lookup()
289 if (!rcu_access_pointer(np->ipv6_fl_list)) in fl6_free_socklist()
293 while ((sfl = rcu_dereference_protected(np->ipv6_fl_list, in fl6_free_socklist()
295 np->ipv6_fl_list = sfl->next; in fl6_free_socklist()
298 fl_release(sfl->fl); in fl6_free_socklist()
319 struct ipv6_txoptions *fl_opt = fl->opt; in fl6_merge_options()
321 if (!fopt || fopt->opt_flen == 0) in fl6_merge_options()
325 opt_space->hopopt = fl_opt->hopopt; in fl6_merge_options()
326 opt_space->dst0opt = fl_opt->dst0opt; in fl6_merge_options()
327 opt_space->srcrt = fl_opt->srcrt; in fl6_merge_options()
328 opt_space->opt_nflen = fl_opt->opt_nflen; in fl6_merge_options()
330 if (fopt->opt_nflen == 0) in fl6_merge_options()
332 opt_space->hopopt = NULL; in fl6_merge_options()
333 opt_space->dst0opt = NULL; in fl6_merge_options()
334 opt_space->srcrt = NULL; in fl6_merge_options()
335 opt_space->opt_nflen = 0; in fl6_merge_options()
337 opt_space->dst1opt = fopt->dst1opt; in fl6_merge_options()
338 opt_space->opt_flen = fopt->opt_flen; in fl6_merge_options()
339 opt_space->tot_len = fopt->tot_len; in fl6_merge_options()
347 return FL_MIN_LINGER*HZ; in check_linger()
350 return ttl*HZ; in check_linger()
357 return -EPERM; in fl6_renew()
360 return -EPERM; in fl6_renew()
363 fl->lastuse = jiffies; in fl6_renew()
364 if (time_before(fl->linger, linger)) in fl6_renew()
365 fl->linger = linger; in fl6_renew()
366 if (time_before(expires, fl->linger)) in fl6_renew()
367 expires = fl->linger; in fl6_renew()
368 if (time_before(fl->expires, fl->lastuse + expires)) in fl6_renew()
369 fl->expires = fl->lastuse + expires; in fl6_renew()
376 fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, in fl_create() argument
384 olen = optlen - CMSG_ALIGN(sizeof(*freq)); in fl_create()
385 err = -EINVAL; in fl_create()
389 err = -ENOMEM; in fl_create()
399 err = -ENOMEM; in fl_create()
400 fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL); in fl_create()
401 if (!fl->opt) in fl_create()
404 memset(fl->opt, 0, sizeof(*fl->opt)); in fl_create()
405 fl->opt->tot_len = sizeof(*fl->opt) + olen; in fl_create()
406 err = -EFAULT; in fl_create()
407 if (copy_from_sockptr_offset(fl->opt + 1, optval, in fl_create()
408 CMSG_ALIGN(sizeof(*freq)), olen)) in fl_create()
412 msg.msg_control = (void *)(fl->opt+1); in fl_create()
415 ipc6.opt = fl->opt; in fl_create()
419 err = -EINVAL; in fl_create()
420 if (fl->opt->opt_flen) in fl_create()
422 if (fl->opt->opt_nflen == 0) { in fl_create()
423 kfree(fl->opt); in fl_create()
424 fl->opt = NULL; in fl_create()
428 fl->fl_net = net; in fl_create()
429 fl->expires = jiffies; in fl_create()
430 err = fl6_renew(fl, freq->flr_linger, freq->flr_expires); in fl_create()
433 fl->share = freq->flr_share; in fl_create()
434 addr_type = ipv6_addr_type(&freq->flr_dst); in fl_create()
437 err = -EINVAL; in fl_create()
440 fl->dst = freq->flr_dst; in fl_create()
441 atomic_set(&fl->users, 1); in fl_create()
442 switch (fl->share) { in fl_create()
447 fl->owner.pid = get_task_pid(current, PIDTYPE_PID); in fl_create()
450 fl->owner.uid = current_euid(); in fl_create()
453 err = -EINVAL; in fl_create()
456 if (fl_shared_exclusive(fl) || fl->opt) { in fl_create()
457 WRITE_ONCE(sock_net(sk)->ipv6.flowlabel_has_excl, 1); in fl_create()
464 kfree(fl->opt); in fl_create()
475 int room = FL_MAX_SIZE - atomic_read(&fl_size); in mem_check()
478 if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK) in mem_check()
490 return -ENOBUFS; in mem_check()
499 sfl->fl = fl; in fl_link()
500 sfl->next = np->ipv6_fl_list; in fl_link()
501 rcu_assign_pointer(np->ipv6_fl_list, sfl); in fl_link()
505 int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq, in ipv6_flowlabel_opt_get() argument
512 freq->flr_label = np->rcv_flowinfo & IPV6_FLOWLABEL_MASK; in ipv6_flowlabel_opt_get()
517 freq->flr_label = np->flow_label; in ipv6_flowlabel_opt_get()
524 if (sfl->fl->label == (np->flow_label & IPV6_FLOWLABEL_MASK)) { in ipv6_flowlabel_opt_get()
526 freq->flr_label = sfl->fl->label; in ipv6_flowlabel_opt_get()
527 freq->flr_dst = sfl->fl->dst; in ipv6_flowlabel_opt_get()
528 freq->flr_share = sfl->fl->share; in ipv6_flowlabel_opt_get()
529 freq->flr_expires = (sfl->fl->expires - jiffies) / HZ; in ipv6_flowlabel_opt_get()
530 freq->flr_linger = sfl->fl->linger / HZ; in ipv6_flowlabel_opt_get()
539 return -ENOENT; in ipv6_flowlabel_opt_get()
545 static int ipv6_flowlabel_put(struct sock *sk, struct in6_flowlabel_req *freq) in ipv6_flowlabel_put() argument
551 if (freq->flr_flags & IPV6_FL_F_REFLECT) { in ipv6_flowlabel_put()
552 if (sk->sk_protocol != IPPROTO_TCP) in ipv6_flowlabel_put()
553 return -ENOPROTOOPT; in ipv6_flowlabel_put()
555 return -ESRCH; in ipv6_flowlabel_put()
556 np->flow_label = 0; in ipv6_flowlabel_put()
562 for (sflp = &np->ipv6_fl_list; in ipv6_flowlabel_put()
564 sflp = &sfl->next) { in ipv6_flowlabel_put()
565 if (sfl->fl->label == freq->flr_label) in ipv6_flowlabel_put()
569 return -ESRCH; in ipv6_flowlabel_put()
571 if (freq->flr_label == (np->flow_label & IPV6_FLOWLABEL_MASK)) in ipv6_flowlabel_put()
572 np->flow_label &= ~IPV6_FLOWLABEL_MASK; in ipv6_flowlabel_put()
573 *sflp = sfl->next; in ipv6_flowlabel_put()
575 fl_release(sfl->fl); in ipv6_flowlabel_put()
580 static int ipv6_flowlabel_renew(struct sock *sk, struct in6_flowlabel_req *freq) in ipv6_flowlabel_renew() argument
589 if (sfl->fl->label == freq->flr_label) { in ipv6_flowlabel_renew()
590 err = fl6_renew(sfl->fl, freq->flr_linger, in ipv6_flowlabel_renew()
591 freq->flr_expires); in ipv6_flowlabel_renew()
598 if (freq->flr_share == IPV6_FL_S_NONE && in ipv6_flowlabel_renew()
599 ns_capable(net->user_ns, CAP_NET_ADMIN)) { in ipv6_flowlabel_renew()
600 struct ip6_flowlabel *fl = fl_lookup(net, freq->flr_label); in ipv6_flowlabel_renew()
603 err = fl6_renew(fl, freq->flr_linger, in ipv6_flowlabel_renew()
604 freq->flr_expires); in ipv6_flowlabel_renew()
609 return -ESRCH; in ipv6_flowlabel_renew()
612 static int ipv6_flowlabel_get(struct sock *sk, struct in6_flowlabel_req *freq, in ipv6_flowlabel_get() argument
621 if (freq->flr_flags & IPV6_FL_F_REFLECT) { in ipv6_flowlabel_get()
622 if (net->ipv6.sysctl.flowlabel_consistency) { in ipv6_flowlabel_get()
624 return -EPERM; in ipv6_flowlabel_get()
627 if (sk->sk_protocol != IPPROTO_TCP) in ipv6_flowlabel_get()
628 return -ENOPROTOOPT; in ipv6_flowlabel_get()
633 if (freq->flr_label & ~IPV6_FLOWLABEL_MASK) in ipv6_flowlabel_get()
634 return -EINVAL; in ipv6_flowlabel_get()
635 if (net->ipv6.sysctl.flowlabel_state_ranges && in ipv6_flowlabel_get()
636 (freq->flr_label & IPV6_FLOWLABEL_STATELESS_FLAG)) in ipv6_flowlabel_get()
637 return -ERANGE; in ipv6_flowlabel_get()
639 fl = fl_create(net, sk, freq, optval, optlen, &err); in ipv6_flowlabel_get()
645 if (freq->flr_label) { in ipv6_flowlabel_get()
646 err = -EEXIST; in ipv6_flowlabel_get()
649 if (sfl->fl->label == freq->flr_label) { in ipv6_flowlabel_get()
650 if (freq->flr_flags & IPV6_FL_F_EXCL) { in ipv6_flowlabel_get()
654 fl1 = sfl->fl; in ipv6_flowlabel_get()
655 if (!atomic_inc_not_zero(&fl1->users)) in ipv6_flowlabel_get()
663 fl1 = fl_lookup(net, freq->flr_label); in ipv6_flowlabel_get()
666 err = -EEXIST; in ipv6_flowlabel_get()
667 if (freq->flr_flags&IPV6_FL_F_EXCL) in ipv6_flowlabel_get()
669 err = -EPERM; in ipv6_flowlabel_get()
670 if (fl1->share == IPV6_FL_S_EXCL || in ipv6_flowlabel_get()
671 fl1->share != fl->share || in ipv6_flowlabel_get()
672 ((fl1->share == IPV6_FL_S_PROCESS) && in ipv6_flowlabel_get()
673 (fl1->owner.pid != fl->owner.pid)) || in ipv6_flowlabel_get()
674 ((fl1->share == IPV6_FL_S_USER) && in ipv6_flowlabel_get()
675 !uid_eq(fl1->owner.uid, fl->owner.uid))) in ipv6_flowlabel_get()
678 err = -ENOMEM; in ipv6_flowlabel_get()
681 if (fl->linger > fl1->linger) in ipv6_flowlabel_get()
682 fl1->linger = fl->linger; in ipv6_flowlabel_get()
683 if ((long)(fl->expires - fl1->expires) > 0) in ipv6_flowlabel_get()
684 fl1->expires = fl->expires; in ipv6_flowlabel_get()
694 err = -ENOENT; in ipv6_flowlabel_get()
695 if (!(freq->flr_flags & IPV6_FL_F_CREATE)) in ipv6_flowlabel_get()
698 err = -ENOMEM; in ipv6_flowlabel_get()
706 fl1 = fl_intern(net, fl, freq->flr_label); in ipv6_flowlabel_get()
710 if (!freq->flr_label) { in ipv6_flowlabel_get()
713 if (copy_to_sockptr_offset(optval, offset, &fl->label, in ipv6_flowlabel_get()
714 sizeof(fl->label))) { in ipv6_flowlabel_get()
729 struct in6_flowlabel_req freq; in ipv6_flowlabel_opt() local
731 if (optlen < sizeof(freq)) in ipv6_flowlabel_opt()
732 return -EINVAL; in ipv6_flowlabel_opt()
733 if (copy_from_sockptr(&freq, optval, sizeof(freq))) in ipv6_flowlabel_opt()
734 return -EFAULT; in ipv6_flowlabel_opt()
736 switch (freq.flr_action) { in ipv6_flowlabel_opt()
738 return ipv6_flowlabel_put(sk, &freq); in ipv6_flowlabel_opt()
740 return ipv6_flowlabel_renew(sk, &freq); in ipv6_flowlabel_opt()
742 return ipv6_flowlabel_get(sk, &freq, optval, optlen); in ipv6_flowlabel_opt()
744 return -EINVAL; in ipv6_flowlabel_opt()
756 #define ip6fl_seq_private(seq) ((struct ip6fl_iter_state *)(seq)->private)
764 for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { in ip6fl_get_first()
765 for_each_fl_rcu(state->bucket, fl) { in ip6fl_get_first()
766 if (net_eq(fl->fl_net, net)) in ip6fl_get_first()
781 if (net_eq(fl->fl_net, net)) in ip6fl_get_next()
786 if (++state->bucket <= FL_HASH_MASK) { in ip6fl_get_next()
787 for_each_fl_rcu(state->bucket, fl) { in ip6fl_get_next()
788 if (net_eq(fl->fl_net, net)) in ip6fl_get_next()
804 --pos; in ip6fl_get_idx()
813 state->pid_ns = proc_pid_ns(file_inode(seq->file)->i_sb); in ip6fl_seq_start()
816 return *pos ? ip6fl_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; in ip6fl_seq_start()
845 "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", in ip6fl_seq_show()
846 (unsigned int)ntohl(fl->label), in ip6fl_seq_show()
847 fl->share, in ip6fl_seq_show()
848 ((fl->share == IPV6_FL_S_PROCESS) ? in ip6fl_seq_show()
849 pid_nr_ns(fl->owner.pid, state->pid_ns) : in ip6fl_seq_show()
850 ((fl->share == IPV6_FL_S_USER) ? in ip6fl_seq_show()
851 from_kuid_munged(seq_user_ns(seq), fl->owner.uid) : in ip6fl_seq_show()
853 atomic_read(&fl->users), in ip6fl_seq_show()
854 fl->linger/HZ, in ip6fl_seq_show()
855 (long)(fl->expires - jiffies)/HZ, in ip6fl_seq_show()
856 &fl->dst, in ip6fl_seq_show()
857 fl->opt ? fl->opt->opt_nflen : 0); in ip6fl_seq_show()
871 if (!proc_create_net("ip6_flowlabel", 0444, net->proc_net, in ip6_flowlabel_proc_init()
873 return -ENOMEM; in ip6_flowlabel_proc_init()
879 remove_proc_entry("ip6_flowlabel", net->proc_net); in ip6_flowlabel_proc_fini()