• Home
  • Raw
  • Download

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_bh(fl->next))
65 for (fl = rcu_dereference_bh(fl->next); \
67 fl = rcu_dereference_bh(fl->next))
70 for (sfl = rcu_dereference_bh(np->ipv6_fl_list); \
72 sfl = rcu_dereference_bh(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()
223 fl->label = htonl(prandom_u32())&IPV6_FLOWLABEL_MASK; in fl_intern()
224 if (fl->label) { in fl_intern()
225 lfl = __fl_lookup(net, fl->label); in fl_intern()
236 * done in ipv6_flowlabel_opt - sock is locked, so new entry in fl_intern()
239 lfl = __fl_lookup(net, fl->label); in fl_intern()
241 atomic_inc(&lfl->users); in fl_intern()
247 fl->lastuse = jiffies; in fl_intern()
248 fl->next = fl_ht[FL_HASH(fl->label)]; in fl_intern()
249 rcu_assign_pointer(fl_ht[FL_HASH(fl->label)], fl); in fl_intern()
268 struct ip6_flowlabel *fl = sfl->fl; in __fl6_sock_lookup()
270 if (fl->label == label && atomic_inc_not_zero(&fl->users)) { in __fl6_sock_lookup()
271 fl->lastuse = jiffies; in __fl6_sock_lookup()
286 if (!rcu_access_pointer(np->ipv6_fl_list)) in fl6_free_socklist()
290 while ((sfl = rcu_dereference_protected(np->ipv6_fl_list, in fl6_free_socklist()
292 np->ipv6_fl_list = sfl->next; in fl6_free_socklist()
295 fl_release(sfl->fl); in fl6_free_socklist()
316 struct ipv6_txoptions *fl_opt = fl->opt; in fl6_merge_options()
318 if (!fopt || fopt->opt_flen == 0) in fl6_merge_options()
322 opt_space->hopopt = fl_opt->hopopt; in fl6_merge_options()
323 opt_space->dst0opt = fl_opt->dst0opt; in fl6_merge_options()
324 opt_space->srcrt = fl_opt->srcrt; in fl6_merge_options()
325 opt_space->opt_nflen = fl_opt->opt_nflen; in fl6_merge_options()
327 if (fopt->opt_nflen == 0) in fl6_merge_options()
329 opt_space->hopopt = NULL; in fl6_merge_options()
330 opt_space->dst0opt = NULL; in fl6_merge_options()
331 opt_space->srcrt = NULL; in fl6_merge_options()
332 opt_space->opt_nflen = 0; in fl6_merge_options()
334 opt_space->dst1opt = fopt->dst1opt; in fl6_merge_options()
335 opt_space->opt_flen = fopt->opt_flen; in fl6_merge_options()
336 opt_space->tot_len = fopt->tot_len; in fl6_merge_options()
344 return FL_MIN_LINGER*HZ; in check_linger()
347 return ttl*HZ; in check_linger()
354 return -EPERM; in fl6_renew()
357 return -EPERM; in fl6_renew()
360 fl->lastuse = jiffies; in fl6_renew()
361 if (time_before(fl->linger, linger)) in fl6_renew()
362 fl->linger = linger; in fl6_renew()
363 if (time_before(expires, fl->linger)) in fl6_renew()
364 expires = fl->linger; in fl6_renew()
365 if (time_before(fl->expires, fl->lastuse + expires)) in fl6_renew()
366 fl->expires = fl->lastuse + expires; in fl6_renew()
373 fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, in fl_create() argument
381 olen = optlen - CMSG_ALIGN(sizeof(*freq)); in fl_create()
382 err = -EINVAL; in fl_create()
386 err = -ENOMEM; in fl_create()
396 err = -ENOMEM; in fl_create()
397 fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL); in fl_create()
398 if (!fl->opt) in fl_create()
401 memset(fl->opt, 0, sizeof(*fl->opt)); in fl_create()
402 fl->opt->tot_len = sizeof(*fl->opt) + olen; in fl_create()
403 err = -EFAULT; in fl_create()
404 if (copy_from_sockptr_offset(fl->opt + 1, optval, in fl_create()
405 CMSG_ALIGN(sizeof(*freq)), olen)) in fl_create()
409 msg.msg_control = (void *)(fl->opt+1); in fl_create()
412 ipc6.opt = fl->opt; in fl_create()
416 err = -EINVAL; in fl_create()
417 if (fl->opt->opt_flen) in fl_create()
419 if (fl->opt->opt_nflen == 0) { in fl_create()
420 kfree(fl->opt); in fl_create()
421 fl->opt = NULL; in fl_create()
425 fl->fl_net = net; in fl_create()
426 fl->expires = jiffies; in fl_create()
427 err = fl6_renew(fl, freq->flr_linger, freq->flr_expires); in fl_create()
430 fl->share = freq->flr_share; in fl_create()
431 addr_type = ipv6_addr_type(&freq->flr_dst); in fl_create()
434 err = -EINVAL; in fl_create()
437 fl->dst = freq->flr_dst; in fl_create()
438 atomic_set(&fl->users, 1); in fl_create()
439 switch (fl->share) { in fl_create()
444 fl->owner.pid = get_task_pid(current, PIDTYPE_PID); in fl_create()
447 fl->owner.uid = current_euid(); in fl_create()
450 err = -EINVAL; in fl_create()
453 if (fl_shared_exclusive(fl) || fl->opt) { in fl_create()
454 WRITE_ONCE(sock_net(sk)->ipv6.flowlabel_has_excl, 1); in fl_create()
461 kfree(fl->opt); in fl_create()
472 int room = FL_MAX_SIZE - atomic_read(&fl_size); in mem_check()
475 if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK) in mem_check()
487 return -ENOBUFS; in mem_check()
496 sfl->fl = fl; in fl_link()
497 sfl->next = np->ipv6_fl_list; in fl_link()
498 rcu_assign_pointer(np->ipv6_fl_list, sfl); in fl_link()
502 int ipv6_flowlabel_opt_get(struct sock *sk, struct in6_flowlabel_req *freq, in ipv6_flowlabel_opt_get() argument
509 freq->flr_label = np->rcv_flowinfo & IPV6_FLOWLABEL_MASK; in ipv6_flowlabel_opt_get()
513 if (np->repflow) { in ipv6_flowlabel_opt_get()
514 freq->flr_label = np->flow_label; in ipv6_flowlabel_opt_get()
521 if (sfl->fl->label == (np->flow_label & IPV6_FLOWLABEL_MASK)) { in ipv6_flowlabel_opt_get()
523 freq->flr_label = sfl->fl->label; in ipv6_flowlabel_opt_get()
524 freq->flr_dst = sfl->fl->dst; in ipv6_flowlabel_opt_get()
525 freq->flr_share = sfl->fl->share; in ipv6_flowlabel_opt_get()
526 freq->flr_expires = (sfl->fl->expires - jiffies) / HZ; in ipv6_flowlabel_opt_get()
527 freq->flr_linger = sfl->fl->linger / HZ; in ipv6_flowlabel_opt_get()
536 return -ENOENT; in ipv6_flowlabel_opt_get()
542 static int ipv6_flowlabel_put(struct sock *sk, struct in6_flowlabel_req *freq) in ipv6_flowlabel_put() argument
548 if (freq->flr_flags & IPV6_FL_F_REFLECT) { in ipv6_flowlabel_put()
549 if (sk->sk_protocol != IPPROTO_TCP) in ipv6_flowlabel_put()
550 return -ENOPROTOOPT; in ipv6_flowlabel_put()
551 if (!np->repflow) in ipv6_flowlabel_put()
552 return -ESRCH; in ipv6_flowlabel_put()
553 np->flow_label = 0; in ipv6_flowlabel_put()
554 np->repflow = 0; in ipv6_flowlabel_put()
559 for (sflp = &np->ipv6_fl_list; in ipv6_flowlabel_put()
561 sflp = &sfl->next) { in ipv6_flowlabel_put()
562 if (sfl->fl->label == freq->flr_label) in ipv6_flowlabel_put()
566 return -ESRCH; in ipv6_flowlabel_put()
568 if (freq->flr_label == (np->flow_label & IPV6_FLOWLABEL_MASK)) in ipv6_flowlabel_put()
569 np->flow_label &= ~IPV6_FLOWLABEL_MASK; in ipv6_flowlabel_put()
570 *sflp = sfl->next; in ipv6_flowlabel_put()
572 fl_release(sfl->fl); in ipv6_flowlabel_put()
577 static int ipv6_flowlabel_renew(struct sock *sk, struct in6_flowlabel_req *freq) in ipv6_flowlabel_renew() argument
586 if (sfl->fl->label == freq->flr_label) { in ipv6_flowlabel_renew()
587 err = fl6_renew(sfl->fl, freq->flr_linger, in ipv6_flowlabel_renew()
588 freq->flr_expires); in ipv6_flowlabel_renew()
595 if (freq->flr_share == IPV6_FL_S_NONE && in ipv6_flowlabel_renew()
596 ns_capable(net->user_ns, CAP_NET_ADMIN)) { in ipv6_flowlabel_renew()
597 struct ip6_flowlabel *fl = fl_lookup(net, freq->flr_label); in ipv6_flowlabel_renew()
600 err = fl6_renew(fl, freq->flr_linger, in ipv6_flowlabel_renew()
601 freq->flr_expires); in ipv6_flowlabel_renew()
606 return -ESRCH; in ipv6_flowlabel_renew()
609 static int ipv6_flowlabel_get(struct sock *sk, struct in6_flowlabel_req *freq, in ipv6_flowlabel_get() argument
618 if (freq->flr_flags & IPV6_FL_F_REFLECT) { in ipv6_flowlabel_get()
619 if (net->ipv6.sysctl.flowlabel_consistency) { in ipv6_flowlabel_get()
621 return -EPERM; in ipv6_flowlabel_get()
624 if (sk->sk_protocol != IPPROTO_TCP) in ipv6_flowlabel_get()
625 return -ENOPROTOOPT; in ipv6_flowlabel_get()
626 np->repflow = 1; in ipv6_flowlabel_get()
630 if (freq->flr_label & ~IPV6_FLOWLABEL_MASK) in ipv6_flowlabel_get()
631 return -EINVAL; in ipv6_flowlabel_get()
632 if (net->ipv6.sysctl.flowlabel_state_ranges && in ipv6_flowlabel_get()
633 (freq->flr_label & IPV6_FLOWLABEL_STATELESS_FLAG)) in ipv6_flowlabel_get()
634 return -ERANGE; in ipv6_flowlabel_get()
636 fl = fl_create(net, sk, freq, optval, optlen, &err); in ipv6_flowlabel_get()
642 if (freq->flr_label) { in ipv6_flowlabel_get()
643 err = -EEXIST; in ipv6_flowlabel_get()
646 if (sfl->fl->label == freq->flr_label) { in ipv6_flowlabel_get()
647 if (freq->flr_flags & IPV6_FL_F_EXCL) { in ipv6_flowlabel_get()
651 fl1 = sfl->fl; in ipv6_flowlabel_get()
652 if (!atomic_inc_not_zero(&fl1->users)) in ipv6_flowlabel_get()
660 fl1 = fl_lookup(net, freq->flr_label); in ipv6_flowlabel_get()
663 err = -EEXIST; in ipv6_flowlabel_get()
664 if (freq->flr_flags&IPV6_FL_F_EXCL) in ipv6_flowlabel_get()
666 err = -EPERM; in ipv6_flowlabel_get()
667 if (fl1->share == IPV6_FL_S_EXCL || in ipv6_flowlabel_get()
668 fl1->share != fl->share || in ipv6_flowlabel_get()
669 ((fl1->share == IPV6_FL_S_PROCESS) && in ipv6_flowlabel_get()
670 (fl1->owner.pid != fl->owner.pid)) || in ipv6_flowlabel_get()
671 ((fl1->share == IPV6_FL_S_USER) && in ipv6_flowlabel_get()
672 !uid_eq(fl1->owner.uid, fl->owner.uid))) in ipv6_flowlabel_get()
675 err = -ENOMEM; in ipv6_flowlabel_get()
678 if (fl->linger > fl1->linger) in ipv6_flowlabel_get()
679 fl1->linger = fl->linger; in ipv6_flowlabel_get()
680 if ((long)(fl->expires - fl1->expires) > 0) in ipv6_flowlabel_get()
681 fl1->expires = fl->expires; in ipv6_flowlabel_get()
691 err = -ENOENT; in ipv6_flowlabel_get()
692 if (!(freq->flr_flags & IPV6_FL_F_CREATE)) in ipv6_flowlabel_get()
695 err = -ENOMEM; in ipv6_flowlabel_get()
703 fl1 = fl_intern(net, fl, freq->flr_label); in ipv6_flowlabel_get()
707 if (!freq->flr_label) { in ipv6_flowlabel_get()
710 if (copy_to_sockptr_offset(optval, offset, &fl->label, in ipv6_flowlabel_get()
711 sizeof(fl->label))) { in ipv6_flowlabel_get()
726 struct in6_flowlabel_req freq; in ipv6_flowlabel_opt() local
728 if (optlen < sizeof(freq)) in ipv6_flowlabel_opt()
729 return -EINVAL; in ipv6_flowlabel_opt()
730 if (copy_from_sockptr(&freq, optval, sizeof(freq))) in ipv6_flowlabel_opt()
731 return -EFAULT; in ipv6_flowlabel_opt()
733 switch (freq.flr_action) { in ipv6_flowlabel_opt()
735 return ipv6_flowlabel_put(sk, &freq); in ipv6_flowlabel_opt()
737 return ipv6_flowlabel_renew(sk, &freq); in ipv6_flowlabel_opt()
739 return ipv6_flowlabel_get(sk, &freq, optval, optlen); in ipv6_flowlabel_opt()
741 return -EINVAL; in ipv6_flowlabel_opt()
753 #define ip6fl_seq_private(seq) ((struct ip6fl_iter_state *)(seq)->private)
761 for (state->bucket = 0; state->bucket <= FL_HASH_MASK; ++state->bucket) { in ip6fl_get_first()
762 for_each_fl_rcu(state->bucket, fl) { in ip6fl_get_first()
763 if (net_eq(fl->fl_net, net)) in ip6fl_get_first()
778 if (net_eq(fl->fl_net, net)) in ip6fl_get_next()
783 if (++state->bucket <= FL_HASH_MASK) { in ip6fl_get_next()
784 for_each_fl_rcu(state->bucket, fl) { in ip6fl_get_next()
785 if (net_eq(fl->fl_net, net)) in ip6fl_get_next()
801 --pos; in ip6fl_get_idx()
810 state->pid_ns = proc_pid_ns(file_inode(seq->file)->i_sb); in ip6fl_seq_start()
813 return *pos ? ip6fl_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; in ip6fl_seq_start()
842 "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", in ip6fl_seq_show()
843 (unsigned int)ntohl(fl->label), in ip6fl_seq_show()
844 fl->share, in ip6fl_seq_show()
845 ((fl->share == IPV6_FL_S_PROCESS) ? in ip6fl_seq_show()
846 pid_nr_ns(fl->owner.pid, state->pid_ns) : in ip6fl_seq_show()
847 ((fl->share == IPV6_FL_S_USER) ? in ip6fl_seq_show()
848 from_kuid_munged(seq_user_ns(seq), fl->owner.uid) : in ip6fl_seq_show()
850 atomic_read(&fl->users), in ip6fl_seq_show()
851 fl->linger/HZ, in ip6fl_seq_show()
852 (long)(fl->expires - jiffies)/HZ, in ip6fl_seq_show()
853 &fl->dst, in ip6fl_seq_show()
854 fl->opt ? fl->opt->opt_nflen : 0); in ip6fl_seq_show()
868 if (!proc_create_net("ip6_flowlabel", 0444, net->proc_net, in ip6_flowlabel_proc_init()
870 return -ENOMEM; in ip6_flowlabel_proc_init()
876 remove_proc_entry("ip6_flowlabel", net->proc_net); in ip6_flowlabel_proc_fini()