diff --git a/arraymap.py b/arraymap.py
index c03050354de5ae9d316e43a99a5a3f526f3db106..56f35366fdc53d04c706b893e6418862f012dd4e 100644
--- a/arraymap.py
+++ b/arraymap.py
@@ -1,6 +1,6 @@
 from struct import pack, unpack
 
-from .ebpf import Map, Memory, Opcode
+from .ebpf import FuncId, Map, Memory, Opcode
 from .bpf import create_map, lookup_elem, MapType, update_elem
 
 
@@ -70,7 +70,7 @@ class ArrayMap(Map):
             ebpf.append(Opcode.ST, 10, 0, stack, 0)
             ebpf.r1 = ebpf.get_fd(fd)
             ebpf.r2 = ebpf.r10 + stack
-            ebpf.call(1)
+            ebpf.call(FuncId.map_lookup_elem)
             with ebpf.If(ebpf.r0 == 0):
                 ebpf.exit()
         ebpf.owners.add(0)
diff --git a/ebpf.py b/ebpf.py
index ca3370920e311fe367eb16a0a9fd46e66374ba53..9049ee4cd4853240ddeace58bde80f99d55ed628 100644
--- a/ebpf.py
+++ b/ebpf.py
@@ -8,6 +8,165 @@ from . import bpf
 Instruction = namedtuple("Instruction",
                          ["opcode", "dst", "src", "off", "imm"])
 
+
+class FuncId(Enum):
+    unspec = 0
+    map_lookup_elem = 1
+    map_update_elem = 2
+    map_delete_elem = 3
+    probe_read = 4
+    ktime_get_ns = 5
+    trace_printk = 6
+    get_prandom_u32 = 7
+    get_smp_processor_id = 8
+    skb_store_bytes = 9
+    l3_csum_replace = 10
+    l4_csum_replace = 11
+    tail_call = 12
+    clone_redirect = 13
+    get_current_pid_tgid = 14
+    get_current_uid_gid = 15
+    get_current_comm = 16
+    get_cgroup_classid = 17
+    skb_vlan_push = 18
+    skb_vlan_pop = 19
+    skb_get_tunnel_key = 20
+    skb_set_tunnel_key = 21
+    perf_event_read = 22
+    redirect = 23
+    get_route_realm = 24
+    perf_event_output = 25
+    skb_load_bytes = 26
+    get_stackid = 27
+    csum_diff = 28
+    skb_get_tunnel_opt = 29
+    skb_set_tunnel_opt = 30
+    skb_change_proto = 31
+    skb_change_type = 32
+    skb_under_cgroup = 33
+    get_hash_recalc = 34
+    get_current_task = 35
+    probe_write_user = 36
+    current_task_under_cgroup = 37
+    skb_change_tail = 38
+    skb_pull_data = 39
+    csum_update = 40
+    set_hash_invalid = 41
+    get_numa_node_id = 42
+    skb_change_head = 43
+    xdp_adjust_head = 44
+    probe_read_str = 45
+    get_socket_cookie = 46
+    get_socket_uid = 47
+    set_hash = 48
+    setsockopt = 49
+    skb_adjust_room = 50
+    redirect_map = 51
+    sk_redirect_map = 52
+    sock_map_update = 53
+    xdp_adjust_meta = 54
+    perf_event_read_value = 55
+    perf_prog_read_value = 56
+    getsockopt = 57
+    override_return = 58
+    sock_ops_cb_flags_set = 59
+    msg_redirect_map = 60
+    msg_apply_bytes = 61
+    msg_cork_bytes = 62
+    msg_pull_data = 63
+    bind = 64
+    xdp_adjust_tail = 65
+    skb_get_xfrm_state = 66
+    get_stack = 67
+    skb_load_bytes_relative = 68
+    fib_lookup = 69
+    sock_hash_update = 70
+    msg_redirect_hash = 71
+    sk_redirect_hash = 72
+    lwt_push_encap = 73
+    lwt_seg6_store_bytes = 74
+    lwt_seg6_adjust_srh = 75
+    lwt_seg6_action = 76
+    rc_repeat = 77
+    rc_keydown = 78
+    skb_cgroup_id = 79
+    get_current_cgroup_id = 80
+    get_local_storage = 81
+    sk_select_reuseport = 82
+    skb_ancestor_cgroup_id = 83
+    sk_lookup_tcp = 84
+    sk_lookup_udp = 85
+    sk_release = 86
+    map_push_elem = 87
+    map_pop_elem = 88
+    map_peek_elem = 89
+    msg_push_data = 90
+    msg_pop_data = 91
+    rc_pointer_rel = 92
+    spin_lock = 93
+    spin_unlock = 94
+    sk_fullsock = 95
+    tcp_sock = 96
+    skb_ecn_set_ce = 97
+    get_listener_sock = 98
+    skc_lookup_tcp = 99
+    tcp_check_syncookie = 100
+    sysctl_get_name = 101
+    sysctl_get_current_value = 102
+    sysctl_get_new_value = 103
+    sysctl_set_new_value = 104
+    strtol = 105
+    strtoul = 106
+    sk_storage_get = 107
+    sk_storage_delete = 108
+    send_signal = 109
+    tcp_gen_syncookie = 110
+    skb_output = 111
+    probe_read_user = 112
+    probe_read_kernel = 113
+    probe_read_user_str = 114
+    probe_read_kernel_str = 115
+    tcp_send_ack = 116
+    send_signal_thread = 117
+    jiffies64 = 118
+    read_branch_records = 119
+    get_ns_current_pid_tgid = 120
+    xdp_output = 121
+    get_netns_cookie = 122
+    get_current_ancestor_cgroup_id = 123
+    sk_assign = 124
+    ktime_get_boot_ns = 125
+    seq_printf = 126
+    seq_write = 127
+    sk_cgroup_id = 128
+    sk_ancestor_cgroup_id = 129
+    ringbuf_output = 130
+    ringbuf_reserve = 131
+    ringbuf_submit = 132
+    ringbuf_discard = 133
+    ringbuf_query = 134
+    csum_level = 135
+    skc_to_tcp6_sock = 136
+    skc_to_tcp_sock = 137
+    skc_to_tcp_timewait_sock = 138
+    skc_to_tcp_request_sock = 139
+    skc_to_udp6_sock = 140
+    get_task_stack = 141
+    load_hdr_opt = 142
+    store_hdr_opt = 143
+    reserve_hdr_opt = 144
+    inode_storage_get = 145
+    inode_storage_delete = 146
+    d_path = 147
+    copy_from_user = 148
+    snprintf_btf = 149
+    seq_printf_btf = 150
+    skb_cgroup_classid = 151
+    redirect_neigh = 152
+    per_cpu_ptr = 153
+    this_cpu_ptr = 154
+    redirect_peer = 155
+
 class Opcode(Enum):
     ADD = 4
     SUB = 0x14
@@ -697,7 +856,8 @@ class EBPF:
         return PseudoFd(self, fd)
 
     def call(self, no):
-        self.append(Opcode.CALL, 0, 0, 0, no)
+        assert isinstance(no, FuncId)
+        self.append(Opcode.CALL, 0, 0, 0, no.value)
         self.owners.add(0)
         self.owners -= set(range(1, 6))
 
diff --git a/ebpf_test.py b/ebpf_test.py
index cede38fb4dfd9b39565a15865a1715307840729d..88b36b14a8cafe85799a2aa7e1b5443514be427f 100644
--- a/ebpf_test.py
+++ b/ebpf_test.py
@@ -3,7 +3,7 @@ from unittest import TestCase, main
 from . import ebpf
 from .arraymap import ArrayMap
 from .ebpf import (
-    AssembleError, EBPF, Opcode, OpcodeFlags, Opcode as O, LocalVar)
+    AssembleError, EBPF, FuncId, Opcode, OpcodeFlags, Opcode as O, LocalVar)
 from .hashmap import HashMap
 from .xdp import XDP
 from .bpf import ProgType, prog_test_run
@@ -417,7 +417,7 @@ class Tests(TestCase):
     def test_call(self):
         e = EBPF()
         e.r8 = 23
-        e.call(5)
+        e.call(FuncId.ktime_get_ns)
         self.assertEqual(e.opcodes, [
             Instruction(opcode=183, dst=8, src=0, off=0, imm=23),
             Instruction(opcode=133, dst=0, src=0, off=0, imm=5)])
diff --git a/hashmap.py b/hashmap.py
index aca0a20bc423c0b543be7a6bb75858b6f6a0a9a5..ec06786fee3e75cdc32414ffdd9e8c2b57c9a6c1 100644
--- a/hashmap.py
+++ b/hashmap.py
@@ -1,7 +1,7 @@
 from contextlib import contextmanager
 from struct import pack, unpack, unpack
 
-from .ebpf import AssembleError, Expression, Opcode, Map
+from .ebpf import AssembleError, Expression, Opcode, Map, FuncId
 from .bpf import create_map, lookup_elem, MapType, update_elem
 
 
@@ -22,7 +22,7 @@ class HashGlobalVar(Expression):
             self.ebpf.append(Opcode.ST, 10, 0, stack, self.count)
             self.ebpf.r1 = self.ebpf.get_fd(self.fd)
             self.ebpf.r2 = self.ebpf.r10 + stack
-            self.ebpf.call(1)
+            self.ebpf.call(FuncId.map_lookup_elem)
             with self.ebpf.If(self.ebpf.r0 == 0):
                 self.ebpf.exit()
             if dst != 0 and force:
@@ -68,7 +68,7 @@ class HashGlobalVarDesc:
                     ebpf.append(Opcode.ST, 10, 0, stack, self.count)
                     ebpf.r2 = ebpf.r10 + stack
                     ebpf.r4 = 0
-                    ebpf.call(2)
+                    ebpf.call(FuncId.map_update_elem)
 
 
 class HashMap(Map):