Defend your CV, line by line
Every claim on your CV is a door an interviewer can open. This turns each line into the questions you'll be asked β the likely ones and the tricky trap follow-ups β with answers you can say out loud. The winning move is never to bluff: own the boundary of what you shipped versus studied, and let mechanism beat buzzword.
π§ The five rules that win the room
Every claim on your CV is a door an interviewer can open. You don't have to be an expert behind every door β you have to own the boundary. Say what you did, say where it stops, and never bluff. Miklos is a maths/OR PhD who shipped the Cloud Onload Operator at Solarflare; he can smell a slogan from across the table. Mechanism beats buzzword every time, and the honest boundary you draw yourself reads as senior β not weak.
- Name the boundary before you're forced to. Volunteer the edge of your knowledge as a feature, not a confession: "I owned the arbiter and the descriptor-facing control path; I did not own the
BSRP/DFEsignal kernels." Drawing the line yourself is the single most senior move you can make β it tells the interviewer you know exactly what you know. - Mechanism, not noun. If you wrote
DMAon your CV, you must be able to explain ownership, visibility, and ordering β not just "DMA moves data." Every term is a promise that you can go one level deeper than the label. Pick the word, then earn it. - Honest gap, then transferable substrate. "I have not shipped a Linux NIC driver. What transfers is hardware-visible state, timing discipline, ownership/ordering, and descriptor/DMA-style programming." Never defensive, never apologetic β gap first, bridge second, in that order.
- Quantify or qualify. If you can't put a number on a claim, describe the mechanism and scope instead of inflating it. "Improved efficiency" with no method is the weakest line you can say out loud; back it with what you actually changed and how you measured it.
- If a skill is thin, pre-decide your honest answer. A calm "I've used it but wouldn't call it a strength" kills the trap on contact. Getting caught overclaiming one skill is the worst outcome in the room β it makes the interviewer re-audit everything else you said. One pre-decided sentence per thin skill buys you the benefit of the doubt on the strong ones.
Header & target line
The target line and contact block. Before a single technical question, the interviewer reads your header. It signals intent: who you are, where you are, and whether this CV was written for them or fired off to everyone. Three things invite a question here β the relocate line, the targeting, and your email domain.
CV line β "Cambridge, UK | Willing to relocate" and "Target: Software Development Engineer (Networking) β AMD Network Solutions | Low-Level C | HW/SW Interface".
Q β You're already in Cambridge and this role is in Cambridge. Why does it say "willing to relocate"?
It's there to signal flexibility and that I'm not a location flight-risk β but for this role it's a non-issue. I'm settled in the Cambridge area near Cambourne, which is ideal for an AMD Network Solutions role. The relocate line is mostly for roles elsewhere; for this one, location works in your favour, not against it.
Q (trap) β This CV is clearly aimed at AMD. Is this a generic networking CV, or do you actually want this team?
It's targeted, and deliberately so. The reason is the Solarflare lineage β Onload, ef_vi, ultra-low-latency NICs β and now the AI-cluster networking direction this group is heading in. That's a specific slope I want to climb, not networking-in-general. The honest framing is: same kind of engineer I already am, adjacent communications domain. If I wanted a generic networking job I'd have applied to twenty of them; I'm here for the datapath lineage.
Q (trap) β Your contact email is a university address, `zewailcity.edu.eg`. Are you still a student?
No β I graduated in 2021. It's just a durable alias I kept after my BSc, nothing more. Happy to give you my personal address; the .edu domain isn't a current affiliation. I don't want it read as anything other than an old forwarding address.
Fix before sending β swap the .edu address for a personal email on the CV itself. A university domain on a professional CV reliably invites the "are you still a student?" question, and that's a question with zero upside β it costs you a beat explaining an alias instead of talking about the work. Pre-empt it by editing the header so the boundary never comes up; keep the "graduated 2021" answer in your pocket only as a fallback if an older copy is in front of them.
Professional profile β the common thread
The professional profile is your thesis statement. It's the first paragraph they read closely, and every noun in it is a promise. The phrases most likely to be probed: the "4+ years" timeline, the "C/C++" split, "Ethernet/TCP/IP foundations," "protocol-driven implementation," and the unspoken question underneath all of it β is wireless really adjacent to Ethernet NICs?
CV line β "Embedded and networking software engineer with 4+ years of commercial low-level C/C++ and Python experience across production RTOS modem firmware, DSP/microcontroller targets and protocol-driven implementationβ¦"
Q β Walk me through "4+ years." When did you actually start?
I interned at MediaTek from January 2022, then moved to full-time Wireless Software Engineer from June 2022 to now. So it's roughly 4.5 years counting the internship, about 4 years full-time β and all of it is commercial, production firmware, not coursework. I count it conservatively on purpose; the number is real either way you slice it.
Q (trap) β You wrote "C/C++." Be honest β how much is C and how much is C++?
The production firmware is C β the RTOS and DSP path is C for determinism and because that's what the existing codebase is. My C++ is on the tooling and test-harness side and personal work. I'm comfortable reading it and solid on the core ideas β RAII, references versus pointers, templates conceptually β but I'd be honest that my shipped depth is C, not modern C++ idioms. I wouldn't pitch myself as a template-metaprogramming engineer, and I don't need to: the datapath code here is overwhelmingly C anyway. Overclaiming C++ would be a needless risk, so I mark the boundary and move on.
Q (trap, the big one for a networking role) β You list "Ethernet/TCP/IP foundations." Define "foundations." What can you actually defend?
"Foundations" means conceptual, not shipped β and the word is chosen deliberately. I can defend: Ethernet framing and the L2/L3 boundary, MAC and IP addressing, ARP, the TCP three-way handshake, reliability via sequence/ack and retransmission, sliding-window flow control, and congestion control at the concept level β slow start, AIMD. Where I'm explicitly not yet deep is the Linux implementation: sk_buff, NAPI, qdiscs, the driver TX/RX path. That's the ramp I'm signing up for, and I'm actively closing it. The one thing I won't let "TCP/IP foundations" be read as is "I've implemented a TCP stack" β I haven't, and the wording is honest precisely so that gap stays visible.
Q β "Protocol-driven implementation" β what does that mean concretely?
It means I take a written specification β 3GPP PHY clauses like TS 38.214 and TS 38.213 β and turn the required behaviour into tested C, including the edge cases the spec implies but doesn't spell out. The discipline is reading a contract and implementing it exactly, then proving it with tests. That same muscle applies directly to implementing a feature from a hardware register spec or a datapath/driver contract β the source document changes, the skill doesn't.
Q (trap) β Your profile leans heavily on wireless. Isn't that a different world from Ethernet NICs?
Different protocol domain, yes β and I won't pretend wireless PHY is Ethernet. But what's the same is the engineering shape: hardware-visible state, constrained C in a hot path, DMA-driven data movement, interrupt timing, ownership and ordering, and debugging across layers. The objects change β from 3GPP state and DSP timing to descriptor rings, PCIe ordering, and packet latency β but how I reason about them doesn't. A descriptor ring is an API for hardware; a doorbell is a trigger with a memory-visibility requirement; a tail-latency deadline is the n2 commit problem I already lived in. The substrate is the hard-won part, and it transfers; the Ethernet specifics are learnable, and I'm already learning them.
Skills Β· languages & toolchain
The skills list is a list of doors. Whatever I wrote here, the interviewer gets to pick the one they want to open β so the burden of proof is on me. My move is to rank these by depth before anyone has to dig, which reframes a long list from "padding" into "honest self-assessment." For the languages and tools below I pre-decide: which are real strengths, which are working tools, and which are honestly just exposure.
Q β Rank these by depth. Which are real strengths versus used-it-once?
Strengths: C, which is my production firmware language, daily. Python next β automation, tooling, test harnesses. Working tier: Shell, Git, GCC, Make β the daily build-and-debug toolchain I live in. Productivity tier: C#, JavaScript/React, Flask, Electron β I've built real internal tools the team uses with these, but they're not where I'd claim systems depth. And LLVM I'd call exposure, not depth β I use it as a toolchain, not its internals. I'd rather under-list and over-deliver than have you find a soft spot I didn't flag.
Q (trap) β You say "C/C++." Be honest β how much is C and how much is C++?
(Say your real split β don't inflate.) My shipped depth is C: the RTOS/DSP transmit path is C for determinism and because that's the existing codebase. My C++ is (name where it really is β tooling, test harnesses, personal projects): I'm comfortable reading it and solid on the core ideas β RAII, references versus pointers, templates conceptually β but I'd be honest that I wouldn't pitch myself as a modern-C++ template-metaprogramming engineer. The good news is the AMD/Solarflare datapath is overwhelmingly C anyway, so overclaiming C++ would be a needless risk. I mark the boundary and move on.
Q (trap) β You listed LLVM. Tell me about your LLVM work.
(Be honest β this one rarely survives a probe if you bluff.) I should be precise: I use it as a toolchain β clang, the sanitizers (ASan/UBSan), clang-tidy β not LLVM internals, IR, or passes. If the team works on the compiler side, that's something I'd be learning from scratch and I'd say so up front. (If even toolchain use is a stretch for you, say so β "it's there as toolchain familiarity, I wouldn't claim depth" β and consider cutting it from the CV; it invites a question with little upside.)
Q (trap) β GCC and LLVM both listed. Name a compiler optimization that can break hand-written low-level code, and how you defend against it.
The classic one is the compiler reordering or eliminating accesses it believes are dead or independent β perfectly legal for ordinary memory, but wrong for memory-mapped hardware registers or lock-free shared state. My defenses: volatile on MMIO so the access isn't optimized away; compiler barriers plus real memory barriers or atomics for ordering between the CPU and DMA; and never relying on undefined behaviour, because the optimizer is allowed to assume UB never happens.
The nuance I'd say unprompted: volatile stops the compiler eliding or reordering the access, but it is not a CPU memory-ordering or multi-core visibility guarantee. For that you need actual barriers or atomics. People conflate the two and ship races that only show up under load β that distinction is exactly the kind of thing that bites you on a descriptor ring before you ring the doorbell.
Q (trap) β C# and React on a low-level C CV. Why shouldn't I read this as unfocused?
Fair question. They're there because I built internal developer tools the team actually uses β Electron/React front-ends, C#/Flask back-ends, including LLM-assisted workflows. The point isn't "I'm a web developer"; it's that I'll build the tooling that makes a low-level team faster β log parsers, trace viewers, triage helpers β instead of just closing my own tickets. For this role that's leverage, explicitly secondary to the C work, not my core. If anything it signals I reduce the team's friction, which on a logs-and-traces-heavy team is real value.
Skills Β· low-level & embedded
This subsection is where "embedded" gets pressure-tested. The trick the interviewer is running is to see whether "RTOS," "MIPS," and "embedded Linux fundamentals" mean shipped depth or rΓ©sumΓ© decoration. I pre-decide the boundary on each: deep where I'm deep (RTOS, HAL, real-time), honest exposure where it's exposure (MIPS, the kernel/driver side of Linux).
Q β Which RTOS? What did "RTOS" actually mean in your work?
(Name it if you can disclose; otherwise:) a commercial RTOS on the modem SoC. Concretely it meant priority-based preemptive scheduling, ISRs with bounded latency, tasks/events/queues for inter-task communication, and being very deliberate about what runs in interrupt context versus task context. My arbiter work was ISR-sensitive and hard real-time, so for me "RTOS" isn't "an OS that happens to be small" β it's about deadlines, priority-inversion risk, and never blocking in the wrong context. The mistakes there aren't crashes you see on a bench; they're timing violations that only appear under load.
Q (trap) β Define hard real-time versus soft real-time. Which were you?
Hard real-time: missing a deadline is a functional failure β the result is wrong or worthless if it's late, not merely degraded. Soft real-time: a missed deadline degrades quality but the system still works. My TX arbiter path was hard real-time: the commit point, n2, was an absolute deadline; miss it and the transmit opportunity is simply gone. That's exactly why the code had to be bounded-latency rather than just fast on average β and it's the same discipline behind tail-latency obsession on a low-latency NIC, where the p99 is the spec, not the mean.
Q (trap) β You listed MIPS. What's your MIPS experience?
(Honest.) MIPS is from embedded coursework and targets, not a recent production claim. I understand the RISC load/store model, the pipeline, branch delay slots historically β but I wouldn't oversell it as commercial MIPS work. If the DSP/MCU ISA matters here I'd ramp on the specific architecture; the ISA-level reasoning transfers, the specifics I'd learn. (If this is thin for you, consider cutting it β it invites a question with very little upside.)
Q (trap) β "embedded Linux fundamentals." What does that cover, and does it include kernel or driver work?
Fundamentals means user-space and system level: the boot/init flow, the /dev and sysfs model, cross-compiling and toolchains, basic device interaction from user space. It does not yet include writing kernel modules or netdev drivers β and that's exactly the ramp I'm signing up for. I'm explicit about that boundary on purpose, because for this role the kernel-driver side is precisely the thing to be honest about. Drawing that line myself reads as senior; getting caught fudging it would make you re-audit everything else I said.
Q β What is a HAL and why does it matter?
A Hardware Abstraction Layer is the thin layer that hides register-level details behind a stable interface, so the upper firmware doesn't bake in chip specifics. It matters for two reasons. One, portability across SoC revisions β when the register map shifts, the logic above doesn't. Two, and more important to me, testability: you can mock the HAL to unit-test the decision logic without any hardware in the loop. It's the same instinct as a clean driver or datapath API β separate "what the hardware does" from "how we drive it" β and it's exactly the seam I lean on to get hardware-facing code under GoogleTest.
Skills Β· networking & protocols
This is the subsection that decides whether I read as a networking engineer or a wireless engineer cosplaying as one. So I keep one line sharp throughout: I have real, shipped protocol-implementation experience β it's wireless PHY, not Ethernet β and my Ethernet/TCP/IP is conceptual foundations, deliberately worded. The honest boundary is the whole point.
Q β "TCP/IP foundations" β what can you actually defend?
Foundations means conceptual, not shipped. I can defend Ethernet framing and the L2/L3 boundary, MAC/IP addressing, ARP, the TCP three-way handshake, reliability through seq/ack and retransmission, sliding-window flow control, and congestion control at the concept level β slow start, AIMD. Where I'm explicitly not yet deep is the Linux implementation β sk_buff, NAPI, qdiscs, the driver TX/RX path β and I'm actively closing that gap. The wording on the CV is "foundations" precisely so it never gets read as "I've implemented a TCP stack." (The full version of this trap, and the wireless-versus-Ethernet framing, lives in the Professional-profile section β this is the short restatement.)
Q (trap) β "packet-processing concepts." Walk me through what happens to a packet on NIC receive.
At a high level: the frame arrives at the MAC/PHY, the NIC does L2 filtering and classification, then DMAs the frame into a host RX buffer that software pre-posted through a descriptor ring, and signals completion β either an interrupt or the driver polling the ring. From there the driver/stack hands it up.
- In the kernel path, that's an
sk_buffwalked up throughNAPI(poll-mode to amortize interrupt cost under load). - In a kernel-bypass path like
ef_vi, the application reads the buffer directly β zero-copy, no per-packet kernel crossing.
I'm strongest on the ownership, descriptor, and DMA mechanics β who owns the buffer when, and the visibility/ordering around the completion. The Linux-stack specifics like NAPI and GRO are where I'm still building depth, and I'll say which is which rather than blur them.
Q (trap) β Where do you have shipped networking experience versus studied?
Shipped: wireless PHY and 3GPP β that's genuine protocol-implementation experience, turning written spec clauses into tested C, just not Ethernet. Studied and ramping: the Ethernet datapath, TCP/IP internals, Linux networking, kernel bypass. I keep that line sharp on purpose, because the worst thing I could do is let "networking and protocols" on the CV imply I've shipped an Ethernet stack. What transfers isn't the protocol β it's the engineering shape: hardware-visible state, constrained C in a hot path, DMA-driven movement, interrupt timing, ownership and ordering. The objects change from 3GPP state and DSP timing to descriptor rings and packet latency; how I reason doesn't.
Skills Β· hardware/software interface
This subsection is about credibility at the silicon boundary. The claims here β VLSI background, FPGA training, hardware-aware debugging β are easy to say and hard to fake under a follow-up. So I'm precise about what's a current skill versus a mental model I carry, and I prove "hardware-aware debugging" with a method, not an adjective.
Q β "VLSI design background." How deep, and is it relevant here?
It's from my BSc β major in VLSI design β plus FPGA training: RTL/Verilog, the synthesis mindset, clock domains, timing. I don't claim to be a current hardware designer, and I'll say that plainly. Why it's still relevant: it means I can read a hardware spec and think about the gate-and-timing reality behind a register, rather than treating the silicon as a black box. When a HW/SW boundary bug shows up, that's the difference between guessing and reasoning about what the hardware can actually do.
Q (trap) β Clock domain crossing β what's the problem and how do you handle it?
When a signal crosses between two unrelated clocks, you can sample it mid-transition and capture metastability, or different bits of a bus can arrive skewed across the boundary. Standard handling:
- Two-flop synchronizers for single-bit control signals β let the metastable state settle before it's used.
- For multi-bit data, either gray coding so only one bit changes at a time (the usual trick for FIFO pointers), or a proper handshake / async FIFO.
It's the hardware version of exactly the same ownership-and-visibility problem I deal with in firmware β making sure a value is stable and visible on the other side of a boundary before anyone acts on it. Whether the boundary is two clocks or a CPU and a DMA engine, the failure mode rhymes.
Q β "hardware-aware debugging" β prove it with a method, not an adjective.
It means I don't stop at the software symptom. My method, in order:
- Reproduce and reduce β get the smallest reliable repro before theorizing.
- Define the owner of each state transition β who is supposed to own this value at this moment.
- Instrument the handoff points, not just the symptom β the bug usually lives in the gap between two components, not inside one function.
- Separate facts from assumptions β write down what the trace actually shows versus what I'm inferring.
- Trace one path end-to-end before changing any code β resist the urge to fix the symptom.
- Add the counter or diagnostic that would have caught it β so the next occurrence is cheap.
The MCU-DSP bug is my worked example of this β a timing and state-visibility interaction that looked like one side's fault but was really a disagreement in an assumption between the two. (The full STAR version of that story lives in the Intern work-experience section.)
Skills Β· algorithms, debug & release
This is the most important skills subsection β it's where my headline algorithm claim lives and where the NIC bridge gets built explicitly. "Arbitration algorithms" is the line most likely to be probed, so I have the TX-arbiter story cold, I name what I owned and what I didn't, and I translate every piece of it into NIC terms before the interviewer has to ask.
Q β "arbitration algorithms" β this is your headline algorithm claim. Walk me through one.
On the DSP I owned a 5G TX-channel arbiter. Multiple scheduler modules submitted transmit requests through an API I designed. At a precise point in the scheduling period the arbiter evaluated the candidates β using n1 as the look-ahead window and n2 as the absolute commit deadline β picked the winning request, and fired a callback into that module, which then programmed the TX accelerators, the bit-rate processing (BSRP) and the digital front end (DFE), by writing descriptors over a shared AXI DMA bus. The whole path was ISR-driven.
I owned the arbiter logic, the request timing, the descriptor-facing control path, and its real-time behaviour. I did not own the BSRP/DFE signal-processing kernels β and I name that boundary up front, because owning the edge of my knowledge reads as senior.
The NIC bridge. That arbiter is conceptually a TX scheduler / packet pacer: choose what transmits, when, under which constraints. The request-API-plus-callback is exactly a descriptor ring plus a doorbell plus a completion. And the n1/n2 "right moment" problem is the deadline and tail-latency problem at the heart of the Solarflare low-latency lineage. A descriptor ring is just an API for hardware; a doorbell is just a trigger with a memory-visibility requirement.
Q (trap) β What made the arbiter hard? Anyone can pick a max.
Right β it was never "pick the biggest." The hard parts were:
- It ran interrupt-driven and ISR-sensitive, so the decision had a bounded-latency budget β a slow decision is a wrong decision.
- Correctness depended on when you evaluated: too early and you miss late-arriving higher-priority requests; too late and you blow the
n2commit deadline. - Ownership and visibility β the winning module programs DMA descriptors, so I had to be certain the descriptor state was fully visible and consistent across the ISR/task boundary before the handoff. The classic race was ringing the doorbell or triggering the DMA before the full descriptor was visible across the
AXIfabric β then the hardware fetches garbage.
So the bugs were ordering and visibility bugs, not arithmetic bugs. I spent the depth of the work enforcing a memory barrier before the doorbell and instrumenting the boundaries to prove the timing margins held under load.
Q (trap) β "core dumps and traces" on a DSP/RTOS β what does a core dump even mean there, and what do you look at first?
On these targets it's typically a crash or exception dump β register state, the call stack, a snapshot of relevant memory β plus runtime trace logs and hardware trace where the silicon supports it. First I look at the faulting context: was it an ISR or a task? Then the stack to find the failing path, and whether it's a hard fault (bad pointer or alignment), a stack overflow, or a watchdog timeout. Then I correlate with the traces to rebuild the sequence that led there, rather than guessing from the final frozen state alone β the dump tells you where it died, the trace tells you how it got there.
Q β "KPI-driven triage" β what KPIs, and how did they drive decisions?
Things like throughput, block and error rates, latency and timing-margin, and stability counters from test runs. KPI-driven means I don't optimize on vibes: if a KPI regresses, I localize which path or feature moved it before touching code, and I use the KPI delta to decide whether a "fix" actually helped or just relocated the problem. That discipline maps straight onto a NIC β p99 latency, drop rate, throughput β where a change that improves the average but worsens the tail is a regression, not a win.
Q (trap) β Google Test on embedded firmware β how do you unit-test code that talks to hardware?
You test the logic, not the silicon. I structure code so the hardware-facing bits sit behind a thin seam β the HAL or an interface β and then in tests I substitute a mock for that seam, so I can drive the decision logic through its edge cases on the host build under GoogleTest, wired into CI. The UL-DAI spec corner cases are a good example of what that lets me exercise without a device in the loop. Hardware-in-the-loop and integration tests cover the real silicon separately. The principle is simple: make the decision logic testable independently of the hardware, and the HAL seam is what makes that possible.
Q β "CI/CD" for firmware β what does that pipeline look like?
A commit triggers a build of the firmware plus the host-side unit tests, runs the GoogleTest suite, then static analysis and lint, and on green proceeds to integration and HIL stages. The value is catching regressions before they ever reach a device or a customer, and keeping release artifacts reproducible. It's the same release discipline Miklos's Cloud Onload work cares about β shippable and supportable, not just fast in a lab. "Correct" in a datapath doesn't only mean the right bits; it means the right bits, at the right microsecond, that you can ship and still debug in the field.
MediaTek Β· Wireless SW Engineer (2022βnow)
This is the section where the CV stops being a list and becomes a set of claims you have to back. Every bullet here is a door an interviewer can open. The winning move is the same one that wins the whole interview: say what you did, say where it stops, and put mechanism behind every noun. Miklos shipped Cloud Onload and will smell a slogan, so lead with how things actually work and name the boundary before you are pushed to it.
The product, and where your firmware sits. This is the first thing to get crisp, because everything else hangs off it.
Q β What's the actual product, and where does your firmware sit in it?
It is modem SoC firmware β the L1 / PHY transmit side. My modules run on the DSP and drive the TX datapath: they take scheduling decisions and protocol behaviour and turn them into programmed transmit actions through the hardware accelerators. I sit right at the hardware/software boundary β below the protocol stack, above the silicon. So when I talk about "firmware" I mean the layer that has to agree with both: it has to honour what the spec says above it, and it has to respect what the hardware can actually do below it, in real time.
Q (trap) β "Production firmware." What does production discipline mean to you that hobby firmware doesn't have?
Production discipline is everything that exists because a bug ships to a customer and is expensive to recall. Concretely: release gating, regression suites that have to stay green, mandatory code review, traceability from a line of code back to a spec clause, staged rollout, and field-supportability. It changes how you write the code, not just how you test it β you are defensive at boundaries, you make state observable so you can debug it remotely, and you are conservative in hot paths because you cannot hot-patch a device in a customer's hands. You optimise for "safe to release and debug in the field," not "works on my bench." That is exactly the discipline a NIC datapath needs, where a regression is a latency tail nobody notices until production load.
TS 38.214 and TS 38.213. If you write the spec numbers on your CV, you have to be able to say what they are without reaching for "it's a 3GPP spec."
Q β What are TS 38.214 and TS 38.213? Don't just say "a spec."
38.213 is NR physical-layer procedures for control β the procedures the UE follows around the control channel: power control, timing, how it reads downlink control information and where it sends uplink control. 38.214 is physical-layer procedures for data β how the data channels are configured and processed: MCS, resource allocation, and the DAI handling. My UL-DAI work lives right at that data-procedure boundary, with one foot in the control side because the DAI is carried in DCI. I'll keep this honest to the clauses I actually touched β I implemented behaviour from these procedures, I did not author the standard.
The correctness-versus-timing tradeoff. This is where they check whether you actually live in a real-time path or just describe one.
Q (trap) β "Balancing correctness vs timing" β give me a concrete tradeoff you made.
The honest shape of it: the most readable version of a piece of protocol logic added branching and repeated computation in a hot, ISR-adjacent path. My order of operations was correctness and testability first β I do not trade those away β then, because of where that code ran and how often, I moved work out of the hot path: precomputed state at configuration time instead of recomputing it per event, and used simpler decision structures at run time. Then I verified with traces and KPIs that I had improved the thing I meant to improve and not just moved cost somewhere else. The part I am careful to state: hot-path design decisions like that I escalate to senior review before shipping. I owned the change at the engineering level; I did not unilaterally redesign the timing budget.
UL-DAI β the spec-to-code ownership story. This is one of your two flagship stories. Its strength is that the whole feature is about detecting something that is missing β which is exactly the flavour of a dropped or reordered packet, or a missed completion, on a NIC.
Q β Explain UL-DAI and DAI to me like I'm not a 5G person.
DAI is the Downlink Assignment Index. In carrier aggregation the UE has to acknowledge multiple downlink transmissions at once, so the network sends a small counter β the DAI β that tells the UE how many assignments it should have seen by now. The UE uses that count to build the right HARQ-ACK feedback. The crucial part is what it buys you: it lets the UE detect a missing assignment instead of silently building misaligned feedback. Without it, if the UE misses one downlink control message, its whole ack/nack bitmap shifts and every subsequent ack is wrong. The DAI is the consistency check that catches the gap. UL-DAI is the uplink side of that mechanism, and the "missing DL DCI reporting" piece is precisely the missing-assignment case: detecting that an expected downlink control message was not received, and handling it so the feedback stays consistent.
The reason this is a strong story for this role: it is a spec-to-code feature whose entire point is correct behaviour when something is missing or out of order. That is the same engineering problem as handling a dropped packet, a reordered descriptor, or a completion that never arrives on a NIC ring. The mechanism transfers even though the protocol does not.
Q (trap) β "Own" is a strong word. What did you own versus the team?
I owned the feature end-to-end at the engineering level: reading the relevant spec clauses, clarifying the edge cases with senior engineers, the C design and implementation in the TX firmware, the GoogleTest coverage, the CI/CD integration, and supporting it through review and issue resolution after release. What I did not own is architectural sign-off β that was a senior/lead decision, and I am deliberate about that line. "Own" for me means I was the engineer accountable for that feature working and being defensible, not that I set the architecture single-handed. I would rather state that boundary myself than have you find it.
Cross-layer root-cause method. Your CV claims you isolate root causes across L1 TX/RX, RF, PA, calibration, and test. The interviewer wants the method, not the adjective.
Q β Pick one cross-layer bug and walk me through the root cause.
I lead with the method, then the example. The method is: reproduce and reduce the failure until it is deterministic enough to study; define which layer owns the suspect state; instrument the handoff points between layers, not just the symptom; separate facts from assumptions; trace one path end-to-end before I change any code; then add the counter or diagnostic that would have caught it next time. The worked example is the MCU-DSP visibility bug or a TX-arbiter ordering bug β in both, the failure was not "in one function," it was in an assumption between two components about who owned a piece of state and when it became visible.
Q (trap) β How do you avoid blaming the wrong layer β for example, "it's RF's fault"?
By separating evidence from interpretation, out loud and on purpose. I bring the trace or the dump and say "here is what the data shows" before anyone has labelled a culprit. The moment you say "it's RF" in a cross-team debug, RF stops investigating and starts defending, and you have lost the people who can actually see their own layer. Keeping everyone looking at the same facts is what makes convergence fast. Premature blame is the single most common way a multi-layer debug goes sideways, and I have watched it happen β so I treat the layer boundary as a thing to instrument, not a thing to accuse.
The "100+ issues" line β volume is not the point. Reframe it before they read it as padding.
Q (trap) β "100+ issues" β is that just volume? What's the skill?
The number is real, but the number is not the skill β the skill is controlling ambiguity. These issues arrive with incomplete logs, a fuzzy repro, and a symptom that could be firmware, RF, calibration, or the test setup itself. My approach is to classify before I dig: is it reproducible, what changed recently, which component is implicated by the evidence we already have, and what evidence is actually missing. Then I reduce it to a smaller, sharper technical question and pull in the right owner early with that framing instead of throwing a raw bug over the wall. That maps directly onto multi-layer NIC issues β a latency spike or a drop could be the driver, the firmware, the queues, PCIe ordering, the application, or the test rig, and the engineer who can narrow that quickly is worth more than the one who can read a single layer deeply. The throughput taught me the triage; the triage is the transferable part.
Q β Tell me about one you escalated wrongly or got one wrong.
Have a real, small one ready β humility here reads as senior, not weak. The frame: my early hypothesis, the specific piece of evidence that disproved it, and the one thing I changed about my process afterwards, for example "now I check the calibration state before I implicate RF." The point is to show the feedback loop, not to confess a disaster.
Improving performance β quantify or qualify, never inflate. This is the weakest kind of CV line if you cannot back it, and Miklos will know that.
Q (trap) β "Improve performance" β quantify it. By how much, measured how?
I describe this by mechanism and scope rather than reaching for a headline number I cannot reconstruct. Concretely: I localised the hot-path work in a given module, moved a computation out of the per-event path, and validated the timing-margin or KPI improvement on test runs. If I have a clean before-and-after figure for a specific change, I give it; if I do not, I say so and describe the change instead of inventing a percentage. I would rather tell you "I moved this work off the per-event path and the timing margin improved on our runs" than quote a number I cannot defend if you push on how it was measured. "Improved efficiency" with no method behind it is the easiest claim in the world to puncture, so I never let it stand alone.
Q β How do you find a bottleneck in a real-time path without a fat profiler?
Cycle counters and timestamps bracketing the suspected section, trace timestamps across the whole path, worst-case-path reasoning rather than averages, and checking what runs in ISR context versus task context and how often each fires. The key point for hard real-time is that I care about the worst case and the jitter, not the mean. A change that improves the average but worsens the tail is a regression in my world, because the tail is where the deadline misses live. That is the same instinct as caring about p99 latency on a NIC instead of throughput β a path that is fast on average but occasionally blows its budget is the dangerous one, and the mean will hide it from you.
Internal tooling and LLM-assisted workflows. This is the line most likely to be read as padding on a low-level C CV. Own why it belongs.
Q (trap) β Is this engineering or is it padding? Why is it on a low-level C CV?
It is leverage, and it is explicitly secondary to the C work. A low-level team drowns in logs, traces, and triage, and I built tools the team actually uses to parse and visualise that and speed up the workflow β log parsers, trace viewers, triage helpers, some with LLM assistance. The signal is not "I'm a web developer"; it is "I will reduce the whole team's friction, not just close my own tickets." For this role that is exactly the kind of person who makes a low-level team faster without being asked. The evidence that it is real and not decoration is adoption β the tools are in active use β and I would rather say "used and relied on" than attach a fabricated efficiency percentage to it.
Q (trap) β "LLM-assisted workflows" β concretely what, and how do you stop it hallucinating into production?
Concretely it is things like log triage, boilerplate generation, and spec-lookup helpers β the boring, high-volume parts. On safety, the rule is simple and I hold it firmly: LLM output is a draft, never an authority. It is never the source of truth for production code or for spec interpretation. Anything it produces goes through the same gate as any other change β reviewed by a human, tested, and traced back to the source spec clause, exactly as if I had typed it myself. The model buys speed on the tedious parts; it does not get to bypass the release gate, and it certainly does not get to interpret 38.214 for me. That distinction β speed on the draft, humans on the gate β is the whole reason it is safe to use it at all.
MediaTek Β· Intern β the MCU-DSP bug
The internship is six months, so the trap is the opposite of the current-role section: here the risk is over-claiming. The win is to be precise about scope β "I contributed to," "I owned the investigation but not the subsystem" β while still showing that the flagship debug was real, hard, and reasoned. As an intern you owned a debugging path, not an architecture, and saying that plainly reads as senior judgement, not as a weak hand.
The NTN proof-of-concept. Domain breadth, honestly scoped.
Q β What's hard about NTN versus terrestrial 5G?
Distance and motion. A satellite link has enormous propagation delay and large Doppler shift, so the assumptions baked into terrestrial timing break. Timing advance has to stretch far beyond its terrestrial range, the RACH and timing procedures have to tolerate a round-trip that is orders of magnitude longer, and you need frequency compensation for the Doppler that a stationary tower never sees. As a proof of concept the goal was to show the protocol could cope with those conditions at all β it was about feasibility, not productisation. It gave me extra protocol-domain exposure early, and I am honest that it was a contribution to a NTN PoC, not a shipped feature I owned.
Q (trap) β How much of this was actually you versus the team?
I contributed within a team effort β I will not dress up an intern's PoC contribution as ownership. It is on the CV for domain breadth, not as a leadership claim. If you want to dig into the part I personally worked, I am happy to, but I will not pretend the PoC was mine to steer.
The Python test automation. Standard early-career leverage β name what it replaced.
Q β What did you automate, and what did it replace?
Repetitive manual validation steps β set up the scenario, run it, collect the results, compare against expected β turned into scripted runs so engineers stopped doing them by hand. It is the classic early-career multiplier: take the thing humans do over and over and make it repeatable, so the time goes into judgement instead of clicking through a procedure. It is also where my habit of reaching for Python for test and tooling started, which carried straight into the internal tools I build now.
The MCU-DSP bug β the flagship intern story. This is the worked example of "I can reason across two execution domains." Tell it as a STAR, and state the intern boundary inside the story so it never sounds inflated.
Q β This is your flagship debug story. Walk me through it, using STAR.
Situation. A feature flow occasionally failed in integration, but the failure refused to point cleanly at one side. From the MCU's view, the DSP had not completed the action it was waiting on; from the DSP's view, its own local state looked entirely fine. So each side could honestly say "it isn't me," which is the signature of a bug that lives in the boundary between them rather than inside either one.
Investigation. I mapped the handshake explicitly: what state the MCU believed it owned, what state the DSP believed it owned, and which events or messages were supposed to move the system from one step to the next. Then I used traces and controlled runs to compare the intended sequence against the sequence that actually happened under the failing conditions. I was not hunting for a wrong line of arithmetic β I was hunting for a place where the two sides disagreed about who had done what, and when.
Root cause. It was a timing and state-visibility interaction. The code was correct under the common timing case β which is exactly why the bench never showed it β but under a specific ordering of events the two sides ended up with inconsistent views of progress. One side moved forward believing a step was done while the other had not yet made that step visible. The logic was right; the assumption about ordering between the two domains was not.
Fix and result. I made the interaction explicit and robust so the two sides could not disagree about progress in that window, and I validated it with repeated runs under the conditions that used to trigger it, so I knew we had fixed the cause and not just papered over the symptom. The interface came out more reliable specifically at the handoff that had been failing.
Lesson. At the hardware/software boundary a bug is often not "in one function" β it is in an assumption between components about ownership and ordering. That is the single most transferable thing I took from it, and it maps directly onto NIC work, where the driver, the firmware, the hardware queues, the DMA engine, and host-visible state all have to agree about who owns a buffer and in what order things become visible. The shape of that MCU-DSP disagreement is the same shape as a doorbell that rings before a descriptor write is visible across the bus.
Q (trap) β As an intern, how much of this was you? Be precise.
I owned the investigation. I reproduced it, did the trace analysis, mapped the intended handshake against the failing sequence, found the ordering case, and contributed to the fix discussion. What I was not is the final architectural owner of that interface β I was an intern, and the subsystem belonged to engineers above me. But I owned enough of the debugging path to learn to reason across two execution domains, and that is the skill I am claiming β not that I redesigned the MCU-DSP architecture at six months in.
Q (trap) β If I asked for the exact code or internals, you'd say it's proprietary. So how do I know it's real?
I cannot share MediaTek internals, that is true β but I can walk you through the method in as much depth as you want, and the method is the part that is both non-proprietary and relevant to you. How I mapped which side owned which state, what the trace actually showed me, why the specific ordering case was the culprit rather than the timing I first suspected, and how I proved the fix held under load instead of assuming it. None of that requires me to leak a register map or a source file. If you push on any beat of it, I get more specific about the reasoning, not more vague β which is the tell that I lived it rather than read it. The reasoning is the transferable asset, and it is exactly what this role is about.
Education & the QKLMS thesis
MSc β Erasmus Mundus, three universities.
Q β Three universities, three countries in two years. What did each one actually contribute?
It is a structured Erasmus Mundus mobility programme, not me bouncing around β Limoges, then Aston, then Brescia, all under one degree. Limoges and Brescia covered the microwave electronics and optics side; Aston was the communication systems and wireless networking component, and that is where I got the distinction. The net is a strong signal-processing and comms-theory foundation, which is the layer right underneath everything I build today.
Information theory.
Q (trap) β You list information theory. State Shannon capacity and tell me what it actually means to you as an engineer.
The ShannonβHartley result: C = BΒ·log2(1 + SNR). Capacity scales linearly with bandwidth B but only logarithmically with SNR, so once you are SNR-limited, throwing more power at the link buys you almost nothing β the bigger levers are bandwidth and spatial dimensions, which is exactly why MIMO matters. The practical thing I carry from it is that every channel has a hard ceiling, and good engineering is about getting close to that ceiling efficiently rather than pretending you can beat it.
Worth saying plainly: I know this as theory I studied, not as something I derived for a living. But it is the kind of result that shapes how I think about any rate-versus-resource tradeoff.
Thesis β QKLMS for massive MIMO.
Q β Explain your thesis in two minutes, no jargon.
Power amplifiers are nonlinear, especially when you drive them hard for efficiency β they distort the signal. In massive MIMO you have a large number of PA chains, so that distortion becomes a real, system-level problem. My thesis was an add-on module that learns the inverse of that nonlinearity and compensates for it, so the output comes out clean. The learning algorithm was Quantized Kernel Least Mean Square, a kernel-adaptive filter.
Breaking the name down: the kernel part is what lets it model nonlinear behaviour without me hand-picking the shape of the distortion; the LMS part is the cheap, gradient-style online update that runs as data streams in; and the quantized part is the actual trick. A plain kernel filter keeps adding every new input to its dictionary, so its memory and compute grow without bound the longer it runs. QKLMS quantizes the input space so nearby inputs reuse an existing dictionary entry instead of adding a new one β that caps dictionary growth and makes the thing deployable.
Q (trap, and note he is a maths PhD) β Why QKLMS over a simpler polynomial or Volterra DPD, or over RLS?
Volterra and polynomial models are the standard approach and they work, but they get unwieldy at high order and can struggle with strong, complex nonlinearities β you are committing to a fixed basis up front. Kernel methods model the nonlinearity more flexibly without me choosing those basis functions by hand. Against RLS, the tradeoff is the classic one: RLS converges faster but costs more per step and is more numerically delicate, while LMS is cheaper and more stable to run online. QKLMS then fixes the kernel method's one fatal flaw β the unbounded dictionary β by quantizing, trading a little accuracy for bounded resources. For an add-on module that has to run forever on streaming data, bounded resources are the thing that wins.
Q (trap) β What is the engineering lesson from that thesis that transfers to this job?
Bounded resources under a streaming, real-time constraint. The whole point of QKLMS is that you cannot let state grow without limit when the data never stops β and that is the same instinct as bounding the work in a hot path, capping queue depth, or keeping a descriptor ring's per-packet cost flat regardless of how long the system has been running. Different domain, identical discipline: the data stream does not stop, so your resource budget has to be designed, not discovered.
BSc β Nanotech and VLSI.
Q (trap) β Your CV says RTOS experience with a Raspberry Pi. A Pi runs Linux. Explain.
It was a coursework project running a real-time, bare-metal-style executive on the Pi rather than stock Linux, specifically to get deterministic timing instead of a general-purpose scheduler. I will be precise about it: that is educational RTOS exposure, and it does not carry the same weight as the commercial RTOS firmware I have shipped at MediaTek. I keep that distinction sharp on purpose β the real RTOS claim is the production modem work, the Pi was where I first met the concept.
Q β Nanotech and VLSI into software. Why the pivot, and is that not a red flag?
It is not a pivot away from anything β it is a move toward the exact line where hardware meets software. VLSI gave me the silicon and timing mental model: what is actually happening behind a register, why clock domains and timing matter. What I found is that I was strongest and most engaged writing the low-level C that drives that hardware, rather than designing the gates themselves. So the trajectory is consistent, not scattered β a hardware-literate software engineer who reads a spec and thinks about the silicon reality behind it. This role is the natural continuation of that line, not a swerve off it.
Training
FPGA Design and Verification (Mentor Graphics), 2017.
Q (trap) β FPGA verification β what does verification actually mean, and have you used it since?
Verification is proving the RTL does what the spec says, as opposed to design, which is writing the RTL in the first place. In practice that means building testbenches, driving stimulus into the design, checking the outputs against expected behaviour, and tracking coverage so you know which cases you have actually exercised. I will be straight that this is 2017 training β it is foundational, not current, and I would not present myself as a working verification engineer today.
The reason I keep it on the CV is that it is the same instinct I apply every day now in test and CI: define the expected behaviour, deliberately drive the edge cases, and measure coverage instead of assuming. The tools changed from RTL testbenches to Google Test and CI pipelines, but the discipline is identical.
LabVIEW, 2017.
Q β LabVIEW β is that relevant here?
It is instrumentation and test-automation background β lab measurement and control. Honestly, it is minor for this role; it sits on the CV as test-and-measurement exposure from early on, not as a strength I would lead with. If it is taking up space you would rather use, I am happy to drop it.
β οΈ Whole-CV curveballs
These are the questions about the whole document rather than any single line β the ones that test how you hold the CV together and whether you can be honest about it under pressure. Have all five pre-decided, because hesitating here reads as someone who has not thought about their own story.
Q β In one sentence, what is the thread connecting all of this?
Low-level C at the hardware-software boundary, under real-time constraints, driven by specs and proven by tests β the domain has been wireless, and I want it to be NIC datapaths. Everything else on the page is evidence for that one sentence.
Q (trap) β What is the weakest part of your CV for this role?
No shipped Linux Ethernet NIC driver, and my networking is wireless-stack rather than Ethernet and TCP/IP. I am not going to dress that up. The reason the ramp is controlled rather than a leap is that I am not changing the kind of engineer I am β hardware-visible state, timing, ownership and ordering, descriptor and DMA-style programming, cross-layer debugging are all things I already do. I am changing the communications domain, not the engineering discipline, and I am already studying the Linux and Ethernet side to close that gap.
Q (trap) β If we hired you, what would you be genuinely bad at for the first three months?
Linux kernel and driver internals, and the team's specific codebase and datapath β I would not be fast on either on day one. My first-90-days plan is concrete:
- Build the thing and run its test suite, so I understand the release loop before I touch code.
- Trace one RX path and one TX path end to end, until I can name every handoff.
- Learn the queue, descriptor, and ownership model for this hardware specifically.
- Take diagnostics and contained bugs first, and stay off the fast path and hardware-visible code until I have earned that surface area.
- Get early review on anything risky rather than discovering I was wrong in production.
The honest version is: I would be productive on contained work quickly and grow into the bigger surface, not the other way around.
Q (trap) β Why should we take the risk on a domain-switcher over someone who has already written netdev drivers?
If you need a netdev expert who is productive on the driver tomorrow, that is a different hire and I would tell you so to your face. But if you want an engineer who reasons correctly at the hardware-software boundary, ramps through real debugging, communicates honestly about what he does and does not know, and grows into the AI-cluster networking direction you are heading β that is exactly what I have been doing for four years, just in wireless. The hard-won part is the substrate: the timing, ownership, and cross-layer reasoning. The Ethernet specifics are learnable, and I am already learning them.
Q β Is there anything on here you would cut or change?
Yes, and I have thought about it. I would tighten the skills list down to what I can defend deeply β I would rather under-list and over-deliver than pad it and get caught. LLVM, MIPS, and C# are honest exposure, not strengths, and I would flag them as exposure before you had to ask. The thing I would never cut is the boundary-drawing itself; being precise about where my knowledge stops is the most useful signal I can give you.
π― Pre-interview hit-list
If you only drill ten things before the interview, drill these β they are the lines an interviewer is most likely to open a door on, and each one has a single tactic that turns it from a trap into a point in your favour. The pattern is the same every time: name what you did, name where it stops, and never bluff across the boundary.
- C/C++ β know your real C-versus-C++ split and lead with it; shipped depth is C, do not let C++ get overclaimed.
- Ethernet/TCP/IP foundations β say foundations means conceptual, not shipped, before they make you say it.
- arbitration algorithms β the TX arbiter story cold, with the n1/n2 deadline and the NIC scheduler bridge.
- UL-DAI / DAI β explain DAI in plain English as detecting a missing assignment, then bridge to dropped or reordered packets.
- MCU-DSP bug β STAR format, method first, with the intern-ownership boundary stated up front.
- Thesis / QKLMS β he is a maths PhD and may engage it; plain-English mechanism plus the bounded-resources transfer lesson.
- 100+ issues β reframe the volume as ambiguity-control and evidence-led triage, not a count.
- LLVM / MIPS / embedded Linux β pre-decided honest exposure, not depth; say so unprompted.
- volatile is not a memory barrier β drop this line yourself the moment compilers or ordering come up.
- The gap line β not changing the kind of engineer I am, changing the communications domain.
Final reminder: the interviewer's real question underneath all of this is whether you are a low-level engineer who can ramp into NIC work, or someone dressing up wireless firmware as networking β and every honest boundary you draw is what answers it the first way.